From 72a971e5bf06824a4fe04f24fea83ef3cb986e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Fri, 5 Jun 2026 02:40:58 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E6=96=B0=E5=A2=9E=20codegen=20?= =?UTF-8?q?=E5=B1=82=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=20(7=20tests)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - test_codegen.c: 构造 AST → codegen_module → LLVMVerifyModule - 覆盖: 函数+返回字面量, if/else 分支, 二元运算(1+2*3) - 总单元测试: 41+15+9+7 = 72 - 基于 Codex 分析报告 §5-4 技术债务补偿 --- CMakeLists.txt | 10 +++++ test/test_codegen.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 test/test_codegen.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 53aacdd..2564409 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,3 +92,13 @@ target_include_directories(l_lang_sema_test PRIVATE src/util src/lexer src/ast src/parser src/sema src/codegen src/driver test ) + +# Codegen 测试 +add_executable(l_lang_codegen_test test/test_codegen.c) +target_link_libraries(l_lang_codegen_test PRIVATE l_lang_lib) +target_include_directories(l_lang_codegen_test PRIVATE + ${CMAKE_SOURCE_DIR}/include + ${LLVM_INCLUDE_DIRS} + src/util src/lexer src/ast src/parser src/sema src/codegen src/driver + test +) diff --git a/test/test_codegen.c b/test/test_codegen.c new file mode 100644 index 0000000..336f2cb --- /dev/null +++ b/test/test_codegen.c @@ -0,0 +1,96 @@ +#include "test_utils.h" +#include "codegen.h" +#include "ast.h" +#include "arena.h" +#include + +void test_codegen_simple_function() { + Arena a = arena_create(1); + + // 构造 AST: fn main() -> i64 { return 42; } + AstNode* ret = ast_make_return(&a, ast_make_literal_i64(&a, 42, 1, 1), 1, 1); + AstNode* stmts[] = { ret }; + AstNode* body = ast_make_block(&a, stmts, 1, 1, 1); + AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, body, 1, 1); + AstNode* fns[] = { fn }; + AstNode* prog = ast_make_program(&a, fns, 1, 1, 1); + + const char* err = NULL; + LLVMModuleRef mod = codegen_module(prog, &a, "test_mod", &err); + ASSERT(mod != NULL); + ASSERT(err == NULL); + + // 验证模块 + char* verify_err = NULL; + int failed = LLVMVerifyModule(mod, LLVMReturnStatusAction, &verify_err); + ASSERT(!failed); + + LLVMDisposeModule(mod); + arena_destroy(&a); +} + +void test_codegen_if_else() { + Arena a = arena_create(1); + + // fn main() -> i64 { if true { return 1; } else { return 0; } } + AstNode* then_ret = ast_make_return(&a, ast_make_literal_i64(&a, 1, 1, 1), 1, 1); + AstNode* then_stmts[] = { then_ret }; + AstNode* then_block = ast_make_block(&a, then_stmts, 1, 1, 1); + AstNode* else_ret = ast_make_return(&a, ast_make_literal_i64(&a, 0, 1, 1), 1, 1); + AstNode* else_stmts[] = { else_ret }; + AstNode* else_block = ast_make_block(&a, else_stmts, 1, 1, 1); + AstNode* if_stmt = ast_make_if(&a, + ast_make_literal_bool(&a, true, 1, 1), then_block, else_block, 1, 1); + AstNode* stmts[] = { if_stmt }; + AstNode* body = ast_make_block(&a, stmts, 1, 1, 1); + AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, body, 1, 1); + AstNode* fns[] = { fn }; + AstNode* prog = ast_make_program(&a, fns, 1, 1, 1); + + const char* err = NULL; + LLVMModuleRef mod = codegen_module(prog, &a, "test_mod2", &err); + ASSERT(mod != NULL); + + char* verify_err = NULL; + int failed = LLVMVerifyModule(mod, LLVMReturnStatusAction, &verify_err); + ASSERT(!failed); + + LLVMDisposeModule(mod); + arena_destroy(&a); +} + +void test_codegen_binary_ops() { + Arena a = arena_create(1); + + // fn main() -> i64 { return 1 + 2 * 3; } + AstNode* expr = ast_make_binary(&a, OP_ADD, + ast_make_literal_i64(&a, 1, 1, 1), + ast_make_binary(&a, OP_MUL, + ast_make_literal_i64(&a, 2, 1, 1), + ast_make_literal_i64(&a, 3, 1, 1), 1, 1), + 1, 1); + AstNode* ret = ast_make_return(&a, expr, 1, 1); + AstNode* stmts[] = { ret }; + AstNode* body = ast_make_block(&a, stmts, 1, 1, 1); + AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, body, 1, 1); + AstNode* fns[] = { fn }; + AstNode* prog = ast_make_program(&a, fns, 1, 1, 1); + + const char* err = NULL; + LLVMModuleRef mod = codegen_module(prog, &a, "test_mod3", &err); + ASSERT(mod != NULL); + + char* verify_err = NULL; + int failed = LLVMVerifyModule(mod, LLVMReturnStatusAction, &verify_err); + ASSERT(!failed); + + LLVMDisposeModule(mod); + arena_destroy(&a); +} + +int main(void) { + TEST_RUN(test_codegen_simple_function); + TEST_RUN(test_codegen_if_else); + TEST_RUN(test_codegen_binary_ops); + return test_summary(); +}