feat: struct参数/返回值 + SourceLoc + 测试补全

- struct 可作函数参数和返回值 (fn make_point -> Point)
- SourceLoc 抽象: 所有 ast_make_* 参数 + AstNode 迁移完毕
- sema: +4 struct 类型检查测试 (字段类型/未定义/数量/嵌套)
- codegen: +2 struct IR 生成测试 (decl + field_access)
- 新增集成测试 14_struct_fn.l

测试: 104 单元 + 14 集成 = 全部通过
This commit is contained in:
2026-06-05 13:29:31 +08:00
parent 4046ab1875
commit da9a7065dd
12 changed files with 481 additions and 168 deletions
+33 -7
View File
@@ -608,10 +608,23 @@ LLVMModuleRef codegen_module(AstNode* ast, Arena* codegen_arena,
AstNode* fn = ast->as.program.functions[i];
LLVMTypeRef* ptypes = arena_alloc(ctx.arena,
fn->as.function.param_count * sizeof(LLVMTypeRef));
for (size_t j = 0; j < fn->as.function.param_count; j++)
ptypes[j] = to_llvm_type(&ctx, fn->as.function.params[j]->as.parameter.type);
LLVMTypeRef fty = LLVMFunctionType(
to_llvm_type(&ctx, fn->as.function.return_type),
for (size_t j = 0; j < fn->as.function.param_count; j++) {
AstNode* param = fn->as.function.params[j];
if (param->as.parameter.type == TYPE_STRUCT &&
param->as.parameter.struct_type_name) {
ptypes[j] = find_struct_type(&ctx, param->as.parameter.struct_type_name);
} else {
ptypes[j] = to_llvm_type(&ctx, param->as.parameter.type);
}
}
LLVMTypeRef ret_ty;
if (fn->as.function.return_type == TYPE_STRUCT &&
fn->as.function.return_struct_type_name) {
ret_ty = find_struct_type(&ctx, fn->as.function.return_struct_type_name);
} else {
ret_ty = to_llvm_type(&ctx, fn->as.function.return_type);
}
LLVMTypeRef fty = LLVMFunctionType(ret_ty,
ptypes, (unsigned)fn->as.function.param_count, false);
LLVMValueRef lfn = LLVMAddFunction(ctx.module, fn->as.function.name, fty);
add_fn(&ctx, fn->as.function.name, lfn);
@@ -630,11 +643,18 @@ LLVMModuleRef codegen_module(AstNode* ast, Arena* codegen_arena,
// 将参数注册为变量
for (size_t j = 0; j < fn->as.function.param_count; j++) {
LLVMValueRef param = LLVMGetParam(lfn, (unsigned)j);
AstNode* pnode = fn->as.function.params[j];
LLVMTypeRef param_ty;
if (pnode->as.parameter.type == TYPE_STRUCT &&
pnode->as.parameter.struct_type_name) {
param_ty = find_struct_type(&ctx, pnode->as.parameter.struct_type_name);
} else {
param_ty = to_llvm_type(&ctx, pnode->as.parameter.type);
}
LLVMValueRef alloca = LLVMBuildAlloca(ctx.builder,
to_llvm_type(&ctx, fn->as.function.params[j]->as.parameter.type),
fn->as.function.params[j]->as.parameter.name);
param_ty, pnode->as.parameter.name);
LLVMBuildStore(ctx.builder, param, alloca);
add_var(&ctx, fn->as.function.params[j]->as.parameter.name, alloca);
add_var(&ctx, pnode->as.parameter.name, alloca);
}
codegen_stmt(&ctx, fn->as.function.body);
@@ -645,6 +665,12 @@ LLVMModuleRef codegen_module(AstNode* ast, Arena* codegen_arena,
cleanup_emit(&ctx, 0);
if (fn->as.function.return_type == TYPE_VOID)
LLVMBuildRetVoid(ctx.builder);
else if (fn->as.function.return_type == TYPE_STRUCT &&
fn->as.function.return_struct_type_name) {
LLVMTypeRef st_ty = find_struct_type(&ctx, fn->as.function.return_struct_type_name);
LLVMBuildRet(ctx.builder, st_ty ? LLVMConstNull(st_ty) :
LLVMConstInt(to_llvm_type(&ctx, TYPE_I64), 0, false));
}
else
LLVMBuildRet(ctx.builder,
(fn->as.function.return_type == TYPE_F64