From 9ff2990724a439f1fc3717699dbf1fd1d434dedb 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 00:49:08 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20LLVM=E7=9B=AE=E6=A0=87=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E8=A7=A3=E8=80=A6=20=E2=80=94=20=E6=8A=BD?= =?UTF-8?q?=E5=8F=96=20target.h/c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 src/codegen/target.h/c: target_init/get_default_triple/create_machine/emit_obj - main.c 移除 inline LLVM Target API 调用,改调 target_* 接口 - codegen.c 专注 AST→IR,不再混入目标平台初始化 基于 Codex 分析报告 4.1 节架构改进建议。 --- src/codegen/target.c | 35 +++++++++++++++++++++++++++++++++++ src/codegen/target.h | 21 +++++++++++++++++++++ src/driver/main.c | 32 +++++++------------------------- 3 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 src/codegen/target.c create mode 100644 src/codegen/target.h diff --git a/src/codegen/target.c b/src/codegen/target.c new file mode 100644 index 0000000..2152844 --- /dev/null +++ b/src/codegen/target.c @@ -0,0 +1,35 @@ +#include "target.h" +#include +#include + +void target_init(void) { + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86Target(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86AsmParser(); +} + +char* target_get_default_triple(void) { + return LLVMGetDefaultTargetTriple(); +} + +LLVMTargetMachineRef target_create_machine(const char* triple) { + LLVMTargetRef target; + char* error = NULL; + if (LLVMGetTargetFromTriple(triple, &target, &error)) { + fprintf(stderr, "目标平台错误: %s\n", error); + LLVMDisposeMessage(error); + return NULL; + } + + return LLVMCreateTargetMachine( + target, triple, "generic", "", + LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault); +} + +int target_emit_obj(LLVMTargetMachineRef tm, LLVMModuleRef module, + const char* filename, char** error_msg) { + return LLVMTargetMachineEmitToFile(tm, module, (char*)filename, + LLVMObjectFile, error_msg); +} diff --git a/src/codegen/target.h b/src/codegen/target.h new file mode 100644 index 0000000..6786d5d --- /dev/null +++ b/src/codegen/target.h @@ -0,0 +1,21 @@ +#ifndef TARGET_H +#define TARGET_H + +#include +#include + +// 初始化 X86 目标平台(LLVMInitializeAllTarget* 的替代,LLVM-C.lib 不导出 All 系列) +void target_init(void); + +// 获取默认目标三元组 +char* target_get_default_triple(void); + +// 从三元组获取目标机 +LLVMTargetMachineRef target_create_machine(const char* triple); + +// 将模块写入目标文件 +// 返回 0 成功,非 0 失败(*error_msg 包含错误信息) +int target_emit_obj(LLVMTargetMachineRef tm, LLVMModuleRef module, + const char* filename, char** error_msg); + +#endif diff --git a/src/driver/main.c b/src/driver/main.c index 7dba356..097899d 100644 --- a/src/driver/main.c +++ b/src/driver/main.c @@ -3,12 +3,11 @@ #include "parser.h" #include "sema.h" #include "codegen.h" +#include "target.h" #include "error.h" #include "arena.h" #include -#include -#include #include #include #include @@ -111,35 +110,18 @@ int main(int argc, char** argv) { printf("IR 已输出到: %s\n", ir_path); LLVMDisposeMessage(ir); } else { - // 初始化 X86 目标(LLVM-C.lib 中没有 InitializeAll 系列符号) - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86Target(); - LLVMInitializeX86TargetMC(); - LLVMInitializeX86AsmPrinter(); - LLVMInitializeX86AsmParser(); + // LLVM 目标平台初始化和目标代码生成 + target_init(); - char* triple = LLVMGetDefaultTargetTriple(); - LLVMTargetRef target; - char* target_error = NULL; - if (LLVMGetTargetFromTriple(triple, &target, &target_error)) { - fprintf(stderr, "目标平台错误: %s\n", target_error); - LLVMDisposeMessage(target_error); LLVMDisposeMessage(triple); - free(source); arena_destroy(&arena); LLVMDisposeModule(module); - return 1; - } - - LLVMTargetMachineRef tm = LLVMCreateTargetMachine( - target, triple, "generic", "", - LLVMCodeGenLevelDefault, LLVMRelocDefault, - LLVMCodeModelDefault); + char* triple = target_get_default_triple(); + LLVMTargetMachineRef tm = target_create_machine(triple); LLVMDisposeMessage(triple); + if (!tm) { free(source); arena_destroy(&arena); LLVMDisposeModule(module); return 1; } - // 输出目标文件 char obj_path[512]; snprintf(obj_path, sizeof(obj_path), "%s.o", input); char* obj_error = NULL; - if (LLVMTargetMachineEmitToFile(tm, module, obj_path, - LLVMObjectFile, &obj_error)) { + if (target_emit_obj(tm, module, obj_path, &obj_error)) { fprintf(stderr, "目标代码生成错误: %s\n", obj_error); LLVMDisposeMessage(obj_error); free(source); arena_destroy(&arena);