fix: 5项立即修复 + 2项尽快修复

立即:
- lexer: token数组容量改为src_len+16 + idx越界防御
- symbol: 4个函数arena_alloc加NULL检查
- codegen: verify_err fallback用arena_strdup替代静态字符串
- codegen: cleanup_list从固定64改为arena动态扩容
- lexer: 标识符/字符串字面量65535字符上限

尽快:
- to_llvm_type: TYPE_STRUCT/TYPE_UNKNOWN/TYPE_ERROR显式case
- LLVMGetValueType2不存在(LLVM 22仍用旧名), 保留GlobalGetValueType
This commit is contained in:
2026-06-05 13:12:00 +08:00
parent af0725caca
commit a7fca5964e
3 changed files with 32 additions and 8 deletions
+16 -4
View File
@@ -50,8 +50,9 @@ typedef struct {
LLVMValueRef strlen_fn; LLVMValueRef strlen_fn;
LLVMValueRef memcpy_fn; LLVMValueRef memcpy_fn;
// 自动内存管理: 追踪需要 free 的 str alloca // 自动内存管理: 追踪需要 free 的 str alloca
LLVMValueRef cleanup_list[64]; LLVMValueRef* cleanup_list;
size_t cleanup_count; size_t cleanup_count;
size_t cleanup_cap;
} CgCtx; } CgCtx;
// === 类型映射(需要 Context=== // === 类型映射(需要 Context===
@@ -61,6 +62,9 @@ static LLVMTypeRef to_llvm_type(CgCtx* ctx, TypeKind kind) {
case TYPE_F64: return LLVMDoubleTypeInContext(ctx->context); case TYPE_F64: return LLVMDoubleTypeInContext(ctx->context);
case TYPE_BOOL: return LLVMInt1TypeInContext(ctx->context); case TYPE_BOOL: return LLVMInt1TypeInContext(ctx->context);
case TYPE_STR: return LLVMPointerType(LLVMInt8TypeInContext(ctx->context), 0); case TYPE_STR: return LLVMPointerType(LLVMInt8TypeInContext(ctx->context), 0);
case TYPE_STRUCT:
case TYPE_UNKNOWN:
case TYPE_ERROR:
default: return LLVMVoidTypeInContext(ctx->context); default: return LLVMVoidTypeInContext(ctx->context);
} }
} }
@@ -350,9 +354,16 @@ static LLVMValueRef codegen_expr(CgCtx* ctx, AstNode* node) {
// === 自动内存管理: 作用域退出时释放 str 堆分配 === // === 自动内存管理: 作用域退出时释放 str 堆分配 ===
static void cleanup_add(CgCtx* ctx, LLVMValueRef alloca) { static void cleanup_add(CgCtx* ctx, LLVMValueRef alloca) {
if (ctx->cleanup_count < 64) { if (ctx->cleanup_count >= ctx->cleanup_cap) {
ctx->cleanup_list[ctx->cleanup_count++] = alloca; size_t new_cap = ctx->cleanup_cap ? ctx->cleanup_cap * 2 : 16;
LLVMValueRef* new_list = arena_alloc(ctx->arena, new_cap * sizeof(LLVMValueRef));
if (!new_list) return;
if (ctx->cleanup_list)
memcpy(new_list, ctx->cleanup_list, ctx->cleanup_count * sizeof(LLVMValueRef));
ctx->cleanup_list = new_list;
ctx->cleanup_cap = new_cap;
} }
ctx->cleanup_list[ctx->cleanup_count++] = alloca;
} }
// 释放从 mark 位置开始的所有 str 变量 // 释放从 mark 位置开始的所有 str 变量
@@ -645,7 +656,8 @@ LLVMModuleRef codegen_module(AstNode* ast, Arena* codegen_arena,
// 验证模块(使用 ReturnStatus 以获取完整错误消息) // 验证模块(使用 ReturnStatus 以获取完整错误消息)
char* verify_err = NULL; char* verify_err = NULL;
if (LLVMVerifyModule(ctx.module, LLVMReturnStatusAction, &verify_err)) { if (LLVMVerifyModule(ctx.module, LLVMReturnStatusAction, &verify_err)) {
*error_msg = verify_err ? verify_err : "模块验证失败(错误消息为 NULL"; *error_msg = verify_err ? verify_err
: arena_strdup(ctx.arena, "LLVM 模块验证失败");
LLVMDisposeBuilder(ctx.builder); LLVMDisposeBuilder(ctx.builder);
*out_context = ctx.context; *out_context = ctx.context;
return NULL; return NULL;
+12 -4
View File
@@ -70,7 +70,10 @@ static TokenKind check_keyword(const Token* tok) {
static Token lex_ident_or_keyword(Lexer* l) { static Token lex_ident_or_keyword(Lexer* l) {
int start = l->pos; int start = l->pos;
while (isalnum(peek(l)) || peek(l) == '_') advance(l); while (isalnum(peek(l)) || peek(l) == '_') {
if (l->pos - start > 65535) break; // 标识符长度上限
advance(l);
}
Token t = make_token(l, TOK_IDENT, start, l->pos - start); Token t = make_token(l, TOK_IDENT, start, l->pos - start);
t.kind = check_keyword(&t); t.kind = check_keyword(&t);
return t; return t;
@@ -79,8 +82,9 @@ static Token lex_ident_or_keyword(Lexer* l) {
Token* lex(Arena* a, const char* source, const char* filename, Token* lex(Arena* a, const char* source, const char* filename,
size_t* count, ErrorInfo* error) { size_t* count, ErrorInfo* error) {
Lexer l = {.src = source, .filename = filename, .pos = 0, .line = 1, .col = 1}; Lexer l = {.src = source, .filename = filename, .pos = 0, .line = 1, .col = 1};
// 预估容量:源码长度的 1/3 // 容量上限: 极端情况每个字符一个 token (如 "(){}+-"), src_len 足够
size_t cap = strlen(source) / 3 + 16; size_t src_len = strlen(source);
size_t cap = src_len + 16;
Token* tokens = arena_alloc(a, cap * sizeof(Token)); Token* tokens = arena_alloc(a, cap * sizeof(Token));
if (!tokens) { *count = 0; return NULL; } if (!tokens) { *count = 0; return NULL; }
size_t idx = 0; size_t idx = 0;
@@ -88,6 +92,7 @@ Token* lex(Arena* a, const char* source, const char* filename,
while (peek(&l) != '\0') { while (peek(&l) != '\0') {
skip_whitespace(&l); skip_whitespace(&l);
if (peek(&l) == '\0') break; if (peek(&l) == '\0') break;
if (idx >= cap) { *count = 0; return NULL; } // 防御
int line = l.line, col = l.col; int line = l.line, col = l.col;
char c = peek(&l); char c = peek(&l);
@@ -96,7 +101,10 @@ Token* lex(Arena* a, const char* source, const char* filename,
else if (c == '"') { else if (c == '"') {
advance(&l); // 跳过开头的 " advance(&l); // 跳过开头的 "
int start = l.pos; int start = l.pos;
while (peek(&l) != '"' && peek(&l) != '\0' && peek(&l) != '\n') advance(&l); while (peek(&l) != '"' && peek(&l) != '\0' && peek(&l) != '\n') {
if (l.pos - start > 65535) break; // 字符串长度上限
advance(&l);
}
int len = l.pos - start; int len = l.pos - start;
if (peek(&l) != '"') { if (peek(&l) != '"') {
*error = (ErrorInfo){.message="未闭合的字符串", .filename=filename, .line=line, .col=col}; *error = (ErrorInfo){.message="未闭合的字符串", .filename=filename, .line=line, .col=col};
+4
View File
@@ -4,6 +4,7 @@
Scope* scope_new(void* alloc, Scope* parent) { Scope* scope_new(void* alloc, Scope* parent) {
Scope* s = (Scope*)arena_alloc_impl(alloc, sizeof(Scope)); Scope* s = (Scope*)arena_alloc_impl(alloc, sizeof(Scope));
if (!s) return NULL;
s->head = NULL; s->head = NULL;
s->parent = parent; s->parent = parent;
return s; return s;
@@ -26,6 +27,7 @@ Symbol* scope_insert(Scope* scope, void* alloc, const char* name,
} }
} }
Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol)); Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol));
if (!sym) return NULL;
sym->name = name; sym->kind = kind; sym->type = type; sym->name = name; sym->kind = kind; sym->type = type;
sym->is_mut = false; sym->return_type = TYPE_VOID; sym->is_mut = false; sym->return_type = TYPE_VOID;
sym->param_types = NULL; sym->param_count = 0; sym->param_types = NULL; sym->param_count = 0;
@@ -46,6 +48,7 @@ Symbol* scope_insert_function(Scope* scope, void* alloc, const char* name,
} }
} }
Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol)); Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol));
if (!sym) return NULL;
sym->name = name; sym->kind = SYM_FUNCTION; sym->type = TYPE_VOID; sym->name = name; sym->kind = SYM_FUNCTION; sym->type = TYPE_VOID;
sym->return_type = ret; sym->param_types = pt; sym->param_count = pc; sym->return_type = ret; sym->param_types = pt; sym->param_count = pc;
sym->struct_field_names = NULL; sym->struct_field_names = NULL;
@@ -66,6 +69,7 @@ Symbol* scope_insert_struct(Scope* scope, void* alloc, const char* name,
} }
} }
Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol)); Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol));
if (!sym) return NULL;
sym->name = name; sym->kind = SYM_STRUCT; sym->type = TYPE_STRUCT; sym->name = name; sym->kind = SYM_STRUCT; sym->type = TYPE_STRUCT;
sym->is_mut = false; sym->return_type = TYPE_VOID; sym->is_mut = false; sym->return_type = TYPE_VOID;
sym->param_types = NULL; sym->param_count = 0; sym->param_types = NULL; sym->param_count = 0;