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:
+33
-7
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user