From a603736f64855873ed15e33a8df3ce42e7e490a9 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 27 Aug 2026 13:14:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9A=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=93=8D=E4=BD=9C=E8=B7=A8=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8F=98=E9=87=8F=EF=BC=88VLogger=EF=BC=89=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E9=97=B4=E6=8E=A5=20global=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/Phase/BuildPipeline.vp | 201 ++++----- App/lib/Phase/Phase1/Phase1Main.vp | 191 ++++----- App/lib/Phase/Phase1/Phase1Scan.vp | 12 +- App/lib/Phase/Phase2/__init__.vp | 461 +++++++++------------ App/lib/Projectrans/Config.vp | 2 +- App/lib/Stub/StubGen/Converter.vp | 12 +- App/lib/Stub/StubMerger/StubMergerBuild.vp | 67 ++- App/lib/Stub/StubMerger/StubMergerStore.vp | 6 +- App/lib/Stub/StubMerger/StubMergerTopo.vp | 6 +- App/lib/core/Gen/AssignGenMixin.vp | 14 +- App/lib/core/Gen/CallGenCtor.vp | 8 +- App/lib/core/Gen/CallGenLeafKit.vp | 8 +- App/lib/core/Gen/CallGenLib.vp | 2 +- App/lib/core/Gen/CallGenMixin.vp | 26 +- App/lib/core/Gen/ClassGenDef.vp | 18 +- App/lib/core/Gen/ClassGenEnum.vp | 139 +++---- App/lib/core/Gen/FuncGenDef.vp | 7 +- App/lib/core/Gen/StmtGenDeclMixin.vp | 12 +- App/lib/core/Gen/StructGenMixin.vp | 128 +++--- App/lib/core/Gen/TypeGenCType.vp | 14 +- App/lib/core/IncludesScanner.vp | 20 +- App/lib/core/VLogger.vp | 72 +--- App/main.vp | 287 +++++-------- 23 files changed, 677 insertions(+), 1036 deletions(-) diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index 24a5dbb..e85a13c 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -83,6 +83,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, declare_only: 0=全量翻译(默认),1=仅注册 struct/enum/union(不翻译方法体) temp_dir: temp 目录路径(非 None 时在翻译前生成 .vpi 存根文件) """ + fb: str = VLogger.fmtbuffer if file_path is None: return None f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) if f.closed: return None @@ -112,12 +113,10 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, # # SyntaxError: GenApi.dump_parse_traceback(file_path) - fb_parse: str = VLogger.fmt_buf() - if fb_parse is not None: - err_line: int = ast.get_parse_err_line() - err_col: int = ast.get_parse_err_col() - viperlib.snprintf(fb_parse, 1024, "解析失败: %s (line %d col %d)", file_path, err_line, err_col) - VLogger.error(fb_parse, "PARSE") + err_line: int = ast.get_parse_err_line() + err_col: int = ast.get_parse_err_col() + viperlib.snprintf(fb, 1024, "解析失败: %s (line %d col %d)", file_path, err_line, err_col) + VLogger.error(fb, "PARSE") return None # 生成 .vpi 存根文件(从 AST 直接生成,在 tr.translate 之前,与 Phase1 一致) # .vpi 供其他模块跨模块查询函数签名和 CTypedef 定义 @@ -185,10 +184,8 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, gen.ExprGenCls.extract_module_docstrings(tree, sha1_val) ret: int = tr.translate(tree) if ret != 0: - fb_tf: str = VLogger.fmt_buf() - if fb_tf is not None: - viperlib.snprintf(fb_tf, 1024, "文件翻译失败: %s", file_path) - VLogger.error(fb_tf, "Translate") + viperlib.snprintf(fb, 1024, "文件翻译失败: %s", file_path) + VLogger.error(fb, "Translate") return None return tr @@ -336,6 +333,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s Returns: 0 成功,非 0 失败 """ + fb: str = VLogger.fmtbuffer if ir_path is None or cc_cmd is None or output_dir is None or module_name is None: return 1 @@ -385,10 +383,8 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s asan_path, ir_path) opt_ret: int = stdlib.system(opt_cmd) if opt_ret != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "opt ASan 插桩失败 (module=%s)", module_name) - VLogger.error(fb, "ASAN") + viperlib.snprintf(fb, 1024, "opt ASan 插桩失败 (module=%s)", module_name) + VLogger.error(fb, "ASAN") return 1 compile_input = asan_path @@ -403,10 +399,8 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s # 避免 subprocess 管道捕获丢失输出 sys_ret: int = stdlib.system(cmd) if sys_ret != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd) - VLogger.error(fb, "LLC") + viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd) + VLogger.error(fb, "LLC") return 1 return 0 @@ -582,6 +576,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: tasks: LlcTask 记录连续数组(stdlib.malloc),每个记录由 init_llc_task 填充。 Returns: 0 全部成功;非 0 有失败(已打印失败模块与命令) """ + fb: str = VLogger.fmtbuffer if tasks is None or task_count <= 0: return 0 # --phase2command 模式:不 spawn 线程,把 opt(ASan)+ llc 命令全部写入 bat @@ -595,10 +590,8 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: _phase2_write_cmd(tsk_p.OptCmd) if tsk_p.LlcCmd is not None: _phase2_write_cmd(tsk_p.LlcCmd) - fb_p2: str = VLogger.fmt_buf() - if fb_p2 is not None: - viperlib.snprintf(fb_p2, 1024, "phase2command 模式:%d 条 llc 命令已写入 %s", task_count, _phase2_cmd_path) - VLogger.info(fb_p2, "phase2cmd") + viperlib.snprintf(fb, 1024, "phase2command 模式:%d 条 llc 命令已写入 %s", task_count, _phase2_cmd_path) + VLogger.info(fb, "phase2cmd") return 0 if max_threads <= 0: max_threads = 1 @@ -638,12 +631,10 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: tsk2: LlcTask | t.CPtr = (LlcTask | t.CPtr)(t.CVoid( t.CUInt64T(tasks) + t.CSizeT(batch_start + j) * slot_size, t.CPtr)) if tsk2 is not None and tsk2.Result != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 编译失败: %s (cmd=%s)", - (tsk2.ModuleSha1 if tsk2.ModuleSha1 is not None else "?"), - (tsk2.LlcCmd if tsk2.LlcCmd is not None else "?")) - VLogger.error(fb, "LLC") + viperlib.snprintf(fb, 1024, "llc 编译失败: %s (cmd=%s)", + (tsk2.ModuleSha1 if tsk2.ModuleSha1 is not None else "?"), + (tsk2.LlcCmd if tsk2.LlcCmd is not None else "?")) + VLogger.error(fb, "LLC") ret = 1 return ret @@ -755,6 +746,7 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f Returns: 0 成功,非 0 失败 """ + fb: str = VLogger.fmtbuffer if output_dir is None or linker_cmd is None or module_name is None: return 1 @@ -772,15 +764,11 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f if includes_binary_dir is not None: extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE) if extra_len > 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "附加 %d 字节的 includes.binary .obj 文件", extra_len) - VLogger.info(fb, "link") + viperlib.snprintf(fb, 1024, "附加 %d 字节的 includes.binary .obj 文件", extra_len) + VLogger.info(fb, "link") else: - fb = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "includes.binary 无 .obj 文件: %s", includes_binary_dir) - VLogger.warning(fb, "link") + viperlib.snprintf(fb, 1024, "includes.binary 无 .obj 文件: %s", includes_binary_dir) + VLogger.warning(fb, "link") # 构造命令: clang++ {obj_path} extra_objs -o {output_dir}/{linker_output} linker_flags # 注意: .obj 文件必须在 -l 库标志之前,否则链接器无法解析符号依赖 @@ -819,14 +807,10 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f VLogger.error("subprocess.run 返回 None", "link") return 1 if result.returncode != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "链接失败,返回码: %d", result.returncode) - VLogger.error(fb, "link") - fb = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "命令: %s", cmd) - VLogger.error(fb, "link") + viperlib.snprintf(fb, 1024, "链接失败,返回码: %d", result.returncode) + VLogger.error(fb, "link") + viperlib.snprintf(fb, 1024, "命令: %s", cmd) + VLogger.error(fb, "link") # 显示链接器错误输出 # 注意: subprocess 在 Windows 下将 stderr 合并到 stdout,result.stderr 总是 None if result.stdout is not None: @@ -839,63 +823,62 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f return 0 -def asm_to_obj(asm_path: str, sha1_val: str, output_dir: str, - triple: str) -> int: - """用 llvm-mc 汇编 .s 源文件为 .obj(切片路径) - - 裸机项目(VKernel 等)含 .s 汇编文件(如 Kernel/intr/isr.s 定义 - isr0/syscall_entry/_per_cpu 等符号)。.s 不经过 TPV 翻译/llc, - 直接用配套的 llvm-mc 汇编为 .obj,obj 路径与其他模块一致 - (output_dir/{sha1前缀}/{sha1}.obj),参与 Phase C 链接。 - - Args: - asm_path: .s 源文件完整路径 - sha1_val: 文件内容 SHA1 前16字符(切片路径用) - output_dir: 输出目录 - triple: 目标 triple(如 x86_64-none-elf) - - Returns: - 0 成功,非 0 失败 - """ - if asm_path is None or sha1_val is None or output_dir is None: - return 1 - obj_path: str = build_sliced_path(output_dir, sha1_val, "obj") - if obj_path is None: - return 1 - trip: str = triple - if trip is None or trip[0] == '\0': - trip = "x86_64-none-elf" - cmd_len: t.CSizeT = len("llvm-mc -triple=") + len(trip) \ - + len(" -filetype=obj -o ") + len(obj_path) + len(asm_path) + 64 - cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 - viperlib.snprintf(cmd, cmd_len, "llvm-mc -triple=%s -filetype=obj -o %s %s", - trip, obj_path, asm_path) - - # --phase2command 模式:命令写入 bat(与 llc/链接一致) - if _phase2_cmd_path is not None: - _phase2_write_cmd(cmd) - return 0 - - result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True) - if result is None: - VLogger.error("llvm-mc subprocess.run 返回 None", "asm") - return 1 - if result.returncode != 0: - if result.stdout is not None: - stdio.printf("%s\n", result.stdout) - if result.stderr is not None: - stdio.printf("%s\n", result.stderr) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llvm-mc 汇编失败,返回码: %d, 命令: %s", - result.returncode, cmd) - VLogger.error(fb, "asm") - return 1 - return 0 - - +def asm_to_obj(asm_path: str, sha1_val: str, output_dir: str, + triple: str) -> int: + """用 llvm-mc 汇编 .s 源文件为 .obj(切片路径) + + 裸机项目(VKernel 等)含 .s 汇编文件(如 Kernel/intr/isr.s 定义 + isr0/syscall_entry/_per_cpu 等符号)。.s 不经过 TPV 翻译/llc, + 直接用配套的 llvm-mc 汇编为 .obj,obj 路径与其他模块一致 + (output_dir/{sha1前缀}/{sha1}.obj),参与 Phase C 链接。 + + Args: + asm_path: .s 源文件完整路径 + sha1_val: 文件内容 SHA1 前16字符(切片路径用) + output_dir: 输出目录 + triple: 目标 triple(如 x86_64-none-elf) + + Returns: + 0 成功,非 0 失败 + """ + fb: str = VLogger.fmtbuffer + if asm_path is None or sha1_val is None or output_dir is None: + return 1 + obj_path: str = build_sliced_path(output_dir, sha1_val, "obj") + if obj_path is None: + return 1 + trip: str = triple + if trip is None or trip[0] == '\0': + trip = "x86_64-none-elf" + cmd_len: t.CSizeT = len("llvm-mc -triple=") + len(trip) \ + + len(" -filetype=obj -o ") + len(obj_path) + len(asm_path) + 64 + cmd: bytes = _mbuddy.alloc(cmd_len) + if cmd is None: + return 1 + viperlib.snprintf(cmd, cmd_len, "llvm-mc -triple=%s -filetype=obj -o %s %s", + trip, obj_path, asm_path) + + # --phase2command 模式:命令写入 bat(与 llc/链接一致) + if _phase2_cmd_path is not None: + _phase2_write_cmd(cmd) + return 0 + + result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True) + if result is None: + VLogger.error("llvm-mc subprocess.run 返回 None", "asm") + return 1 + if result.returncode != 0: + if result.stdout is not None: + stdio.printf("%s\n", result.stdout) + if result.stderr is not None: + stdio.printf("%s\n", result.stderr) + viperlib.snprintf(fb, 1024, "llvm-mc 汇编失败,返回码: %d, 命令: %s", + result.returncode, cmd) + VLogger.error(fb, "asm") + return 1 + return 0 + + def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT, temp_dir: str, output_dir: str, module_name: str, cc_cmd: str, cc_flags: str) -> int: @@ -913,16 +896,15 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT, Returns: 0 成功,非 0 失败 """ + fb: str = VLogger.fmtbuffer if ir_buf is None or temp_dir is None or output_dir is None or module_name is None: return 1 # Step 1: 写 .ll 文件 ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name) if ret != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "写 .ll 失败: %s", module_name) - VLogger.error(fb, "compile") + viperlib.snprintf(fb, 1024, "写 .ll 失败: %s", module_name) + VLogger.error(fb, "compile") return 1 # Step 2: 构造切片 .ll 路径并编译 → .obj @@ -932,10 +914,8 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT, ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags) if ret != 0: - fb = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 编译失败: %s", module_name) - VLogger.error(fb, "compile") + viperlib.snprintf(fb, 1024, "llc 编译失败: %s", module_name) + VLogger.error(fb, "compile") return 1 return 0 @@ -956,6 +936,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: t.CSizeT, Returns: 0 成功,非 0 失败 """ + fb: str = VLogger.fmtbuffer if obj_paths is None or obj_paths_len == 0 or linker_cmd is None: return 1 @@ -1064,8 +1045,6 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: t.CSizeT, stdio.printf("=== clang++ 链接错误输出 ===\n%s\n", result.stdout) if result.stderr is not None: stdio.printf("=== clang++ stderr ===\n%s\n", result.stderr) - fb: str = VLogger.fmt_buf() - if fb is not None: viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", result.returncode, cmd) VLogger.error(fb, "link") return 1 diff --git a/App/lib/Phase/Phase1/Phase1Main.vp b/App/lib/Phase/Phase1/Phase1Main.vp index 4be4167..e070821 100644 --- a/App/lib/Phase/Phase1/Phase1Main.vp +++ b/App/lib/Phase/Phase1/Phase1Main.vp @@ -56,6 +56,7 @@ import lib.core.Gen.GenApi as GenApi def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, log: VLogger.Logger | t.CPtr) -> int: """Phase1: 扫描 includes 目录,按需翻译并生成 stub""" + fb: str = VLogger.fmtbuffer if includes_dir is None or temp_dir is None: VLogger.error("includes_dir 或 temp_dir 为空,无法运行 Phase1", "Phase1") return 1 @@ -71,19 +72,17 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 确保 temp 目录存在(build_dir/temp 可能尚未创建) BuildPipeline.ensure_dir(temp_dir) - if log is not None: - log.banner("Phase1: 扫描 includes(按需翻译)") + log.banner("Phase1: 扫描 includes(按需翻译)") # 扫描 includes 目录(含每文件 SHA1 计算计时) t_scan0: t.CUInt64T = w32.win32base.GetTickCount64() result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir) t_scan1: t.CUInt64T = w32.win32base.GetTickCount64() - fb_scan: str = VLogger.fmt_buf() - if fb_scan is not None: - viperlib.snprintf(fb_scan, 1024, - "扫描 includes 总耗时: %llu ms (%d 文件, 含 SHA1 计算)", - t_scan1 - t_scan0, result.Count if result is not None else 0) - VLogger.info(fb_scan, "Phase1") + fb: str = VLogger.fmtbuffer + viperlib.snprintf(fb, 1024, + "扫描 includes 总耗时: %llu ms (%d 文件, 含 SHA1 计算)", + t_scan1 - t_scan0, result.Count if result is not None else 0) + VLogger.info(fb, "Phase1") if result is None: VLogger.error("扫描失败", "Phase1") return 1 @@ -271,17 +270,13 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 1a-pre 阶段总耗时(全部 includes 文件读+parse+import 依赖扫描) t_pre1: t.CUInt64T = w32.win32base.GetTickCount64() - fb_pre: str = VLogger.fmt_buf() - if fb_pre is not None: - viperlib.snprintf(fb_pre, 1024, "1a-pre 总耗时: %llu ms (%d 文件扫描 import 依赖)", - t_pre1 - t_pre0, result.Count) - VLogger.info(fb_pre, "Phase1") + viperlib.snprintf(fb, 1024, "1a-pre 总耗时: %llu ms (%d 文件扫描 import 依赖)", + t_pre1 - t_pre0, result.Count) + VLogger.info(fb, "Phase1") if p1a_failed > 0: - fb_p1apre: str = VLogger.fmt_buf() - if fb_p1apre is not None: - viperlib.snprintf(fb_p1apre, 1024, "Phase 1a-pre 有 %d 个文件扫描失败", p1a_failed) - VLogger.error(fb_p1apre, "Phase1") + viperlib.snprintf(fb, 1024, "Phase 1a-pre 有 %d 个文件扫描失败", p1a_failed) + VLogger.error(fb, "Phase1") return 1 # ============================================================ @@ -374,12 +369,10 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, tc_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(topo_count_box, t.CPtr)) if tc_ptr is not None: topo_count = tc_ptr[0] - fb_topo: str = VLogger.fmt_buf() - if fb_topo is not None: - viperlib.snprintf(fb_topo, 1024, - "拓扑排序: %d 个类, %d 个文件按依赖顺序处理", - class_count_scanned, topo_count) - VLogger.info(fb_topo, "Phase1") + viperlib.snprintf(fb, 1024, + "拓扑排序: %d 个类, %d 个文件按依赖顺序处理", + class_count_scanned, topo_count) + VLogger.info(fb, "Phase1") else: VLogger.error("拓扑排序失败(类继承依赖无法解析),终止编译", "Phase1") return 1 @@ -518,13 +511,11 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, p1a_reg += 1 # 逐文件进度日志(parse/translate 两段,定位 1a 卡点) - fb_1a: str = VLogger.fmt_buf() - if fb_1a is not None: - viperlib.snprintf(fb_1a, 1024, - "[%d/%d] 1a: %s (parse=%llu ms, translate=%llu ms, total=%llu ms)", - i + 1, iter_count, file_path_r, - t_fa1 - t_fa0, t_fa2 - t_fa1, t_fa2 - t_fa0) - VLogger.info(fb_1a, "Phase1") + viperlib.snprintf(fb, 1024, + "[%d/%d] 1a: %s (parse=%llu ms, translate=%llu ms, total=%llu ms)", + i + 1, iter_count, file_path_r, + t_fa1 - t_fa0, t_fa2 - t_fa1, t_fa2 - t_fa0) + VLogger.info(fb, "Phase1") # 释放 Translator 的 C malloc 资源 if tr_r._global_names is not None: @@ -539,17 +530,13 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 1a 阶段总耗时(struct/enum/union 注册,含每文件读+parse+翻译声明) t_a1: t.CUInt64T = w32.win32base.GetTickCount64() - fb_a: str = VLogger.fmt_buf() - if fb_a is not None: - viperlib.snprintf(fb_a, 1024, "1a 总耗时: %llu ms (注册 struct/enum, reg=%d skp=%d)", - t_a1 - t_a0, p1a_reg, p1a_skp) - VLogger.info(fb_a, "Phase1") + viperlib.snprintf(fb, 1024, "1a 总耗时: %llu ms (注册 struct/enum, reg=%d skp=%d)", + t_a1 - t_a0, p1a_reg, p1a_skp) + VLogger.info(fb, "Phase1") if p1a_fl > 0: - fb_p1ar: str = VLogger.fmt_buf() - if fb_p1ar is not None: - viperlib.snprintf(fb_p1ar, 1024, "Phase 1a 有 %d 个文件 struct 注册失败", p1a_fl) - VLogger.error(fb_p1ar, "Phase1") + viperlib.snprintf(fb, 1024, "Phase 1a 有 %d 个文件 struct 注册失败", p1a_fl) + VLogger.error(fb, "Phase1") return 1 # 释放拓扑排序资源(topo_order/topo_count_box 保留到 Phase 1b 结束, @@ -669,17 +656,13 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 1b-pre 阶段总耗时(vpi 预生成) t_pv1: t.CUInt64T = w32.win32base.GetTickCount64() - fb_pv: str = VLogger.fmt_buf() - if fb_pv is not None: - viperlib.snprintf(fb_pv, 1024, "1b-pre 总耗时: %llu ms (vpi 预生成)", - t_pv1 - t_pv0) - VLogger.info(fb_pv, "Phase1") + viperlib.snprintf(fb, 1024, "1b-pre 总耗时: %llu ms (vpi 预生成)", + t_pv1 - t_pv0) + VLogger.info(fb, "Phase1") if p1bpre_failed > 0: - fb_p1bpre: str = VLogger.fmt_buf() - if fb_p1bpre is not None: - viperlib.snprintf(fb_p1bpre, 1024, "Phase 1b-pre 有 %d 个文件 vpi 预生成失败", p1bpre_failed) - VLogger.error(fb_p1bpre, "Phase1") + viperlib.snprintf(fb, 1024, "Phase 1b-pre 有 %d 个文件 vpi 预生成失败", p1bpre_failed) + VLogger.error(fb, "Phase1") return 1 # 遍历每个文件(拓扑序优先:父类所在文件先翻译,确保跨模块 vtable @@ -748,17 +731,13 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, stdlib.free(text_path) # text.ll 不存在,需要重新翻译 rp: str = entry.RelPath - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "text.ll 不存在,重新翻译: %s(sha1=%s)", rp, sha1) - VLogger.info(fb, "Phase1") + viperlib.snprintf(fb, 1024, "text.ll 不存在,重新翻译: %s(sha1=%s)", rp, sha1) + VLogger.info(fb, "Phase1") else: # stub 不存在,需要翻译 rp: str = entry.RelPath - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "翻译: %s(sha1=%s)", rp, sha1) - VLogger.info(fb, "Phase1") + viperlib.snprintf(fb, 1024, "翻译: %s(sha1=%s)", rp, sha1) + VLogger.info(fb, "Phase1") stdlib.free(stub_path) @@ -769,17 +748,13 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, file_path: str = entry.Path f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) if f is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "无法打开(None): %s", file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, "无法打开(None): %s", file_path) + VLogger.error(fb, "Phase1") failed += 1 continue if f.closed: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "无法打开: %s", file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, "无法打开: %s", file_path) + VLogger.error(fb, "Phase1") failed += 1 continue @@ -792,10 +767,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, bytes_read: LONG = f.read_all(src_buf, Phase1.SRC_BUF_SIZE) f.close() if bytes_read <= 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "读取失败: %s", file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, "读取失败: %s", file_path) + VLogger.error(fb, "Phase1") stdlib.free(src_buf) failed += 1 continue @@ -814,10 +787,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, tokens: ast.Token | t.CPtr = ast.tokenize(lx) tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) if tree is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "AST 解析失败: %s", file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, "AST 解析失败: %s", file_path) + VLogger.error(fb, "Phase1") stdlib.free(src_buf) failed += 1 continue @@ -874,11 +845,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # (崩溃点漂移排查:把"翻译过程中随机崩"变成确定性定位) pre_rc: t.CInt = mb.check_alive_blocks(mark1) if pre_rc != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, - "内存损坏(翻译前存活块, rc=%d): %s", pre_rc, file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, + "内存损坏(翻译前存活块, rc=%d): %s", pre_rc, file_path) + VLogger.error(fb, "Phase1") stdlib.exit(1) ret: int = tr.translate(tree) @@ -887,15 +856,11 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 诊断:translate 正常返回(若挂起在 translate 内部,此行不会打印, # 用于区分"translate 内部挂起"与"后续 dump 挂起") if ret == 0: - fb_done: str = VLogger.fmt_buf() - if fb_done is not None: - viperlib.snprintf(fb_done, 1024, "翻译完成(translate返回): %s", file_path) - VLogger.info(fb_done, "Phase1") + viperlib.snprintf(fb, 1024, "翻译完成(translate返回): %s", file_path) + VLogger.info(fb, "Phase1") if ret != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "翻译失败: %s", file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, "翻译失败: %s", file_path) + VLogger.error(fb, "Phase1") stdlib.free(src_buf) if tr._global_names is not None: stdlib.free(tr._global_names) @@ -910,11 +875,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 时链表成环卡死"变成"定位到 translate 期间写穿发生的文件"。 post_rc: t.CInt = mb.check_alive_blocks(mark1) if post_rc != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, - "内存损坏(translate后存活块, rc=%d): %s", post_rc, file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, + "内存损坏(translate后存活块, rc=%d): %s", post_rc, file_path) + VLogger.error(fb, "Phase1") stdlib.exit(1) # dump stub IR(declarations only) @@ -967,13 +930,11 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 计时点 3:dump(stub+text)完成;输出单文件三段耗时 t_f3: t.CUInt64T = w32.win32base.GetTickCount64() - fb_t: str = VLogger.fmt_buf() - if fb_t is not None: - viperlib.snprintf(fb_t, 1024, - "[%d/%d] 翻译: %s (parse=%llu ms, translate=%llu ms, dump=%llu ms, total=%llu ms)", - i + 1, loop_n_b, file_path, - t_f1 - t_f0, t_f2 - t_f1, t_f3 - t_f2, t_f3 - t_f0) - VLogger.info(fb_t, "Phase1") + viperlib.snprintf(fb, 1024, + "[%d/%d] 翻译: %s (parse=%llu ms, translate=%llu ms, dump=%llu ms, total=%llu ms)", + i + 1, loop_n_b, file_path, + t_f1 - t_f0, t_f2 - t_f1, t_f3 - t_f2, t_f3 - t_f0) + VLogger.info(fb, "Phase1") # save dependencies(_imported_modules) for Phase B deps_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "deps.txt") @@ -1010,11 +971,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # rc 语义(self_check):1/2=越界,3=对齐错,4=free list 成环/超步数 chk_rc: t.CInt = mb.check_alive_blocks(mark1) if chk_rc != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, - "内存损坏(存活块 header, rc=%d): %s", chk_rc, file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, + "内存损坏(存活块 header, rc=%d): %s", chk_rc, file_path) + VLogger.error(fb, "Phase1") stdlib.exit(1) # A/B 实验结论(已确认):禁用 reset_to 后 stdarg 仍崩 → 越界写是根因, # 与回收/UAF 无关。恢复 reset_to,改用块尾 canary(check_alive_blocks 校验) @@ -1022,20 +981,16 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, mb.reset_to(mark1) sc_rc: t.CInt = mb.self_check() if sc_rc != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, - "内存损坏(free list, rc=%d): %s", sc_rc, file_path) - VLogger.error(fb, "Phase1") + viperlib.snprintf(fb, 1024, + "内存损坏(free list, rc=%d): %s", sc_rc, file_path) + VLogger.error(fb, "Phase1") stdlib.exit(1) # 1b 阶段总耗时(全量翻译 + dump) t_b1: t.CUInt64T = w32.win32base.GetTickCount64() - fb_b: str = VLogger.fmt_buf() - if fb_b is not None: - viperlib.snprintf(fb_b, 1024, "1b 总耗时: %llu ms (全量翻译, trans=%d skip=%d fail=%d)", - t_b1 - t_b0, translated, skipped, failed) - VLogger.info(fb_b, "Phase1") + viperlib.snprintf(fb, 1024, "1b 总耗时: %llu ms (全量翻译, trans=%d skip=%d fail=%d)", + t_b1 - t_b0, translated, skipped, failed) + VLogger.info(fb, "Phase1") # 释放 Phase 1b 使用的拓扑排序资源 if topo_order is not None: @@ -1043,16 +998,12 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, if topo_count_box is not None: mb.free(topo_count_box) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "完成: 翻译=%d 跳过=%d 失败=%d", translated, skipped, failed) - VLogger.info(fb, "Phase1") + viperlib.snprintf(fb, 1024, "完成: 翻译=%d 跳过=%d 失败=%d", translated, skipped, failed) + VLogger.info(fb, "Phase1") if failed > 0: - fb_fail: str = VLogger.fmt_buf() - if fb_fail is not None: - viperlib.snprintf(fb_fail, 1024, "Phase1 有 %d 个文件翻译失败", failed) - VLogger.error(fb_fail, "Phase1") + viperlib.snprintf(fb, 1024, "Phase1 有 %d 个文件翻译失败", failed) + VLogger.error(fb, "Phase1") return 1 # 释放可达 SHA1 集合(如果分配了) diff --git a/App/lib/Phase/Phase1/Phase1Scan.vp b/App/lib/Phase/Phase1/Phase1Scan.vp index 033cb15..707c72a 100644 --- a/App/lib/Phase/Phase1/Phase1Scan.vp +++ b/App/lib/Phase/Phase1/Phase1Scan.vp @@ -341,10 +341,8 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy | t.CPtr, handled_count += 1 stdlib.free(src_buf_pg) if handled_count > 0: - fb_gpre2: str = VLogger.fmt_buf() - if fb_gpre2 is not None: - viperlib.snprintf(fb_gpre2, 1024, "mark1 前永久池预注册 %d 个 includes 泛型类模板", handled_count) - VLogger.info(fb_gpre2, "Phase1") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "mark1 前永久池预注册 %d 个 includes 泛型类模板", handled_count) + VLogger.info(VLogger.fmtbuffer, "Phase1") return handled_count # ============================================================ # _FindClassDefSha1 - 在扁平数组中查找类名对应的定义文件 SHA1 @@ -386,10 +384,8 @@ def _ScanTreeForContainers(node: ast.AST | t.CPtr, # 递归深度守卫:AST 损坏成自引用环(字段/children 回指祖先)时无限 # 递归直至栈耗尽(每个 includes 文件 parse 后必执行)。fail-fast 终止。 if depth > 128: - fb_stc: str = VLogger.fmt_buf() - if fb_stc is not None: - viperlib.snprintf(fb_stc, 256, "容器扫描递归过深(AST 环或嵌套超过 128 层)") - VLogger.error(fb_stc, "Phase1") + viperlib.snprintf(VLogger.fmtbuffer, 256, "容器扫描递归过深(AST 环或嵌套超过 128 层)") + VLogger.error(VLogger.fmtbuffer, "Phase1") sys.exit(1) if node is None: return diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 54362e7..83ede30 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -41,17 +41,12 @@ SRC_BUF_SIZE: t.CDefine = 1048576 # CompilerFactory.get_perm_pool。增大到 128 留余量) MAX_SRC_FILES: t.CDefine = 128 -# 全局栈金丝雀(避免局部变量改变栈布局) -_g_canary: t.CUInt32T - - @t.NoVTable class SrcFileEntry: """源文件条目""" Path: str # 完整路径 Sha1: str # SHA1 前16字符 - # ============================================================ # _ScanDirForPyFiles - 递归扫描目录,收集 .vp/.py 文件到 entries # @@ -157,10 +152,9 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy | t.CPtr, ent.Path = full_path ent.Sha1 = sha1_val file_count += 1 - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s (sha1=%s)", fname, sha1_val) - VLogger.info(fb, "project") + + viperlib.snprintf(VLogger.fmtbuffer, 1024, "%s (sha1=%s)", fname, sha1_val) + VLogger.info(VLogger.fmtbuffer, "project") stdlib.free(sbuf) # full_path 不释放:ent.Path 引用它 @@ -260,10 +254,9 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy | t.CPtr, ent.Path = full_path ent.Sha1 = sha1_val file_count += 1 - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s (asm sha1=%s)", fname, sha1_val) - VLogger.info(fb, "project") + + viperlib.snprintf(VLogger.fmtbuffer, 1024, "%s (asm sha1=%s)", fname, sha1_val) + VLogger.info(VLogger.fmtbuffer, "project") # full_path 不释放:ent.Path 引用它 if w32.win32file.FindNextFileA(handle, find_data) == 0: @@ -347,10 +340,8 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy | t.CPtr, handled += 1 stdlib.free(src_buf_pa) if handled > 0: - fb_pg3: str = VLogger.fmt_buf() - if fb_pg3 is not None: - viperlib.snprintf(fb_pg3, 1024, "mark2 前预注册 %d 个 App 泛型类模板", handled) - VLogger.info(fb_pg3, "PhaseA") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "mark2 前预注册 %d 个 App 泛型类模板", handled) + VLogger.info(VLogger.fmtbuffer, "PhaseA") return handled @@ -367,18 +358,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, Returns: 0 成功,非 0 失败 """ + fb: str = VLogger.fmtbuffer if source_dir is None: VLogger.error("source_dir 为空", "project") return 1 - # === 栈金丝雀检查(全局变量,不影响栈布局)=== - global _g_canary - _g_canary = 305419896 - - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "多文件项目编译: %s", source_dir) - VLogger.info(fb, "project") + viperlib.snprintf(fb, 1024, "多文件项目编译: %s", source_dir) + VLogger.info(fb, "project") # === 1. 递归扫描 source_dir 下的 .vp/.py 文件(包括子目录)=== entry_size: t.CSizeT = SrcFileEntry.__sizeof__() @@ -388,10 +374,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, string.memset(entries, 0, MAX_SRC_FILES * entry_size) file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "共 %d 个源文件", file_count) - VLogger.info(fb, "project") + viperlib.snprintf(fb, 1024, "共 %d 个源文件", file_count) + VLogger.info(fb, "project") # 扫描 .s 汇编文件(独立数组,不参与 Phase A 翻译,Phase B 后 llvm-mc 汇编) asm_entries: SrcFileEntry | t.CPtr = stdlib.malloc(MAX_SRC_FILES * entry_size) @@ -401,10 +385,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, string.memset(asm_entries, 0, MAX_SRC_FILES * entry_size) asm_file_count: int = _ScanDirForAsmFiles(mb, source_dir, asm_entries, entry_size, 0, MAX_SRC_FILES) if asm_file_count > 0: - fb_asm: str = VLogger.fmt_buf() - if fb_asm is not None: - viperlib.snprintf(fb_asm, 1024, "汇编文件 %d 个(llvm-mc 汇编参与链接)", asm_file_count) - VLogger.info(fb_asm, "project") + viperlib.snprintf(fb, 1024, "汇编文件 %d 个(llvm-mc 汇编参与链接)", asm_file_count) + VLogger.info(fb, "project") if file_count == 0: stdlib.free(entries) @@ -446,10 +428,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, VLogger.error("includes 扫描失败,无法填充 Sha1Store", "project") if inc_scan_result is not None: inc_filled: int = StubMergerStore.PopulateSha1MapStore(inc_scan_result) - fb_inc: str = VLogger.fmt_buf() - if fb_inc is not None: - viperlib.snprintf(fb_inc, 1024, "Phase2 自主填充 includes Sha1Store: %d 个", inc_filled) - VLogger.info(fb_inc, "project") + viperlib.snprintf(fb, 1024, "Phase2 自主填充 includes Sha1Store: %d 个", inc_filled) + VLogger.info(fb, "project") # 追加 App 源文件 SHA1 到 _sha1_map.txt(人类可读输出,程序内部不读取此文件) # 格式: {sha1}:{rel_path}\n (保留目录结构,如 lib/core/VLogger.vp) @@ -478,10 +458,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, # 同步追加到内存存储器(供跨模块 CDefine 查找) # rel_path_am 格式如 "lib/core/StubMerger.vp",与 _sha1_map.txt 一致 if StubMergerStore.AppendToSha1MapStore(ent_am.Sha1, rel_path_am) != 0: - fb_apf: str = VLogger.fmt_buf() - if fb_apf is not None: - viperlib.snprintf(fb_apf, 1024, "AppendToSha1MapStore 失败: %s", rel_path_am) - VLogger.error(fb_apf, "project") + viperlib.snprintf(fb, 1024, "AppendToSha1MapStore 失败: %s", rel_path_am) + VLogger.error(fb, "project") app_filled += 1 # 写入 _sha1_map.txt(人类可读输出) if not mf.closed and line_am is not None: @@ -492,10 +470,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, stdlib.free(line_am) if not mf.closed: mf.close() - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "已追加 %d 个 App 文件到 _sha1_map.txt 和内存存储器", app_filled) - VLogger.info(fb, "project") + viperlib.snprintf(fb, 1024, "已追加 %d 个 App 文件到 _sha1_map.txt 和内存存储器", app_filled) + VLogger.info(fb, "project") stdlib.free(map_path_am) # 模块 SHA1 映射已由 PopulateSha1MapStore + AppendToSha1MapStore 统一填充到 @@ -586,10 +562,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, # OOM 清理:回收本文件 AST(vpi 已写盘;mark2 后持久数据已 stdlib 化) mb.reset_to(mark2) if vpi_failed_p2 > 0: - fb_vp2: str = VLogger.fmt_buf() - if fb_vp2 is not None: - viperlib.snprintf(fb_vp2, 1024, "Phase A-pre-vpi 有 %d 个文件 vpi 预生成失败", vpi_failed_p2) - VLogger.error(fb_vp2, "PhaseA") + viperlib.snprintf(fb, 1024, "Phase A-pre-vpi 有 %d 个文件 vpi 预生成失败", vpi_failed_p2) + VLogger.error(fb, "PhaseA") return 1 @@ -603,8 +577,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, app_deps_buf: bytes = None app_deps_len: t.CSizeT = 0 if do_phase1 != 0: - if log is not None: - log.banner("Phase A: 生成 stub + text") + log.banner("Phase A: 生成 stub + text") # === Phase A-pre-inc: includes 预注册 struct + 依赖填充 === # 必须在 App 源文件预注册之前执行:App 源文件(strict_mode=1)可能继承 @@ -691,18 +664,14 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, for si_inc_f in range(store_count_inc_pre): if inc_fail_flags[si_inc_f] != 0: rel_f: str = store_rel_inc_pre + t.CSizeT(si_inc_f) * StubMerger.MAX_REL_PATH_LEN - fb_inc_f: str = VLogger.fmt_buf() - if fb_inc_f is not None: - viperlib.snprintf(fb_inc_f, 1024, - "includes 预注册失败: %s(文件无法翻译,可能是语法/解析/编译错误),终止编译", - rel_f) - VLogger.error(fb_inc_f, "prePhaseA") + viperlib.snprintf(fb, 1024, + "includes 预注册失败: %s(文件无法翻译,可能是语法/解析/编译错误),终止编译", + rel_f) + VLogger.error(fb, "prePhaseA") sys.exit(1) stdlib.free(inc_fail_flags) - fb_inc_pre: str = VLogger.fmt_buf() - if fb_inc_pre is not None: - viperlib.snprintf(fb_inc_pre, 1024, "includes 预注册 + 依赖填充: %d/%d", deps_filled_pre, store_count_inc_pre) - VLogger.info(fb_inc_pre, "prePhaseA") + viperlib.snprintf(fb, 1024, "includes 预注册 + 依赖填充: %d/%d", deps_filled_pre, store_count_inc_pre) + VLogger.info(fb, "prePhaseA") # === Phase A-pre: 预注册所有源文件的 struct/enum/union === # 解决循环引用问题:circ_a 翻译时需要知道 circ_b.ClassB 的 struct 定义 @@ -725,10 +694,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, pkg_pre = GenApi.compute_package_from_relpath(mb, rel_path_pre) tr_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1) if tr_pre is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path) - VLogger.error(fb, "PhaseA") + viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path) + VLogger.error(fb, "PhaseA") # OOM 清理:回收本 App 文件预注册翻译的瞬时数据 mb.reset_to(mark2) struct_count_after: int = GenApi.get_struct_count() @@ -832,97 +799,95 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, # (含 SHA1)——精确定位是哪个依赖未完成(通常是其自身依赖链 # 上某个文件先失败,text.ll 从未落盘)。全部直接依赖已就绪仍 # pending 时,说明缺失在传递依赖/MRO/vpi 侧,据此缩小排查范围。 - fb_dp: str = VLogger.fmt_buf() - if fb_dp is not None: - miss_dp: bytes = stdlib.malloc(768) - if miss_dp is not None: - miss_dp[0] = '\0' - md_cnt: int = 0 - if tr_a._imported_modules is not None: - im_dp_len: t.CSizeT = string.strlen(tr_a._imported_modules) - im_dp_pos: t.CSizeT = 0 - while im_dp_pos < im_dp_len: - im_dp_start: t.CSizeT = im_dp_pos - while im_dp_pos < im_dp_len and tr_a._imported_modules[im_dp_pos] != ' ': - im_dp_pos += 1 - im_dp_mod_len: t.CSizeT = im_dp_pos - im_dp_start - if im_dp_pos < im_dp_len: - im_dp_pos += 1 - if im_dp_mod_len == 0: - continue - im_dp_buf: bytes = stdlib.malloc(im_dp_mod_len + 1) - if im_dp_buf is None: - continue - string.strncpy(im_dp_buf, tr_a._imported_modules + im_dp_start, im_dp_mod_len) - im_dp_buf[im_dp_mod_len] = '\0' - # 别名/基名解析:精确匹配 → 别名还原(from_imports - # "别名:模块真名",import X as Y 的 Y)→ 后缀匹配兜底。 - # 别名还原必须优先于裸名后缀:store 可能同时存在 - # "vpsdk.process" 与 "VKernel.Kernel.sched.process", - # 裸名 "process" 后缀匹配会命中先扫描的内核模块 → - # 依赖探测误报内核缺 text.ll(Phase A 永不收敛)。 - im_dp_sha1: str = StubMergerStore.LookupSha1ByModName(im_dp_buf) - if im_dp_sha1 is None: - # 改名别名(import X as Y):从 _from_imports 查 Y→X 还原真名, - # 再精确/后缀查 SHA1。LookupSha1ByAlias 只精确匹配——store 键 - # 是全路径模块名(Kernel.drivers.fs.fat32.fat32_diskio)时 - # fat32_diskio 精确不中 → 别名依赖误判 miss → 依赖未就绪死锁 - # (fat32_types 依赖 diskio → Phase A 无法收敛,VKernel 根因)。 - real_dp: str = StubMergerStore.LookupModNameByAlias(tr_a._from_imports, im_dp_buf) - if real_dp is not None: - im_dp_sha1 = StubMergerStore.LookupSha1ByModName(real_dp) - if im_dp_sha1 is None: - im_dp_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(real_dp) - if im_dp_sha1 is None: - im_dp_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(im_dp_buf) - im_dp_resolved: int = 0 - im_dp_missing: int = 0 - if im_dp_sha1 is not None: - im_dp_resolved = 1 - im_dp_txt: str = StubMergerCollect._sliced_path( - temp_dir, td_len_pa, im_dp_sha1, "text.ll") - if im_dp_txt is not None: - im_dp_f: fileio.File | t.CPtr = fileio.File(im_dp_txt, fileio.MODE.R) - if im_dp_f.closed: - im_dp_missing = 1 - else: - im_dp_f.close() - stdlib.free(im_dp_txt) - else: + miss_dp: bytes = stdlib.malloc(768) + if miss_dp is not None: + miss_dp[0] = '\0' + md_cnt: int = 0 + if tr_a._imported_modules is not None: + im_dp_len: t.CSizeT = string.strlen(tr_a._imported_modules) + im_dp_pos: t.CSizeT = 0 + while im_dp_pos < im_dp_len: + im_dp_start: t.CSizeT = im_dp_pos + while im_dp_pos < im_dp_len and tr_a._imported_modules[im_dp_pos] != ' ': + im_dp_pos += 1 + im_dp_mod_len: t.CSizeT = im_dp_pos - im_dp_start + if im_dp_pos < im_dp_len: + im_dp_pos += 1 + if im_dp_mod_len == 0: + continue + im_dp_buf: bytes = stdlib.malloc(im_dp_mod_len + 1) + if im_dp_buf is None: + continue + string.strncpy(im_dp_buf, tr_a._imported_modules + im_dp_start, im_dp_mod_len) + im_dp_buf[im_dp_mod_len] = '\0' + # 别名/基名解析:精确匹配 → 别名还原(from_imports + # "别名:模块真名",import X as Y 的 Y)→ 后缀匹配兜底。 + # 别名还原必须优先于裸名后缀:store 可能同时存在 + # "vpsdk.process" 与 "VKernel.Kernel.sched.process", + # 裸名 "process" 后缀匹配会命中先扫描的内核模块 → + # 依赖探测误报内核缺 text.ll(Phase A 永不收敛)。 + im_dp_sha1: str = StubMergerStore.LookupSha1ByModName(im_dp_buf) + if im_dp_sha1 is None: + # 改名别名(import X as Y):从 _from_imports 查 Y→X 还原真名, + # 再精确/后缀查 SHA1。LookupSha1ByAlias 只精确匹配——store 键 + # 是全路径模块名(Kernel.drivers.fs.fat32.fat32_diskio)时 + # fat32_diskio 精确不中 → 别名依赖误判 miss → 依赖未就绪死锁 + # (fat32_types 依赖 diskio → Phase A 无法收敛,VKernel 根因)。 + real_dp: str = StubMergerStore.LookupModNameByAlias(tr_a._from_imports, im_dp_buf) + if real_dp is not None: + im_dp_sha1 = StubMergerStore.LookupSha1ByModName(real_dp) + if im_dp_sha1 is None: + im_dp_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(real_dp) + if im_dp_sha1 is None: + im_dp_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(im_dp_buf) + im_dp_resolved: int = 0 + im_dp_missing: int = 0 + if im_dp_sha1 is not None: + im_dp_resolved = 1 + im_dp_txt: str = StubMergerCollect._sliced_path( + temp_dir, td_len_pa, im_dp_sha1, "text.ll") + if im_dp_txt is not None: + im_dp_f: fileio.File | t.CPtr = fileio.File(im_dp_txt, fileio.MODE.R) + if im_dp_f.closed: im_dp_missing = 1 + else: + im_dp_f.close() + stdlib.free(im_dp_txt) else: - # 内置模块(t/c)不生成 text.ll,解析不到不算缺失 - if string.strcmp(im_dp_buf, "t") == 0 or string.strcmp(im_dp_buf, "c") == 0: - im_dp_resolved = 2 - if im_dp_missing != 0 or im_dp_resolved == 0: - if md_cnt > 0 and string.strlen(miss_dp) < 700: - string.strcat(miss_dp, ", ") - if string.strlen(miss_dp) < 700: - if im_dp_missing != 0: - viperlib.snprintf(miss_dp + string.strlen(miss_dp), - 768 - string.strlen(miss_dp), - "%s(%s)缺text.ll", im_dp_buf, im_dp_sha1) - else: - viperlib.snprintf(miss_dp + string.strlen(miss_dp), - 768 - string.strlen(miss_dp), - "%s(未解析-改名别名?)", im_dp_buf) - md_cnt += 1 - stdlib.free(im_dp_buf) - if md_cnt > 0: - viperlib.snprintf(fb_dp, 1024, - "Phase A 依赖未就绪,下遍重试: %s | 依赖探测明细: %s", - ent.Path, miss_dp) - else: - viperlib.snprintf(fb_dp, 1024, - "Phase A 依赖未就绪,下遍重试: %s | 直接依赖 text.ll 均已生成" - "(缺失可能在传递依赖/MRO/vpi 侧)", ent.Path) - stdlib.free(miss_dp) + im_dp_missing = 1 + else: + # 内置模块(t/c)不生成 text.ll,解析不到不算缺失 + if string.strcmp(im_dp_buf, "t") == 0 or string.strcmp(im_dp_buf, "c") == 0: + im_dp_resolved = 2 + if im_dp_missing != 0 or im_dp_resolved == 0: + if md_cnt > 0 and string.strlen(miss_dp) < 700: + string.strcat(miss_dp, ", ") + if string.strlen(miss_dp) < 700: + if im_dp_missing != 0: + viperlib.snprintf(miss_dp + string.strlen(miss_dp), + 768 - string.strlen(miss_dp), + "%s(%s)缺text.ll", im_dp_buf, im_dp_sha1) + else: + viperlib.snprintf(miss_dp + string.strlen(miss_dp), + 768 - string.strlen(miss_dp), + "%s(未解析-改名别名?)", im_dp_buf) + md_cnt += 1 + stdlib.free(im_dp_buf) + if md_cnt > 0: + viperlib.snprintf(fb, 1024, + "Phase A 依赖未就绪,下遍重试: %s | 依赖探测明细: %s", + ent.Path, miss_dp) else: - viperlib.snprintf(fb_dp, 1024, - "Phase A 依赖未就绪,下遍重试: %s", ent.Path) - # --nowarn-register 亦抑制此类 Phase A 依赖重试 WARN(刷屏收敛) - if VLogger.nowarn_register() == 0: - VLogger.warning(fb_dp, "PhaseA-DBG") + viperlib.snprintf(fb, 1024, + "Phase A 依赖未就绪,下遍重试: %s | 直接依赖 text.ll 均已生成" + "(缺失可能在传递依赖/MRO/vpi 侧)", ent.Path) + stdlib.free(miss_dp) + else: + viperlib.snprintf(fb, 1024, + "Phase A 依赖未就绪,下遍重试: %s", ent.Path) + # --nowarn-register 亦抑制此类 Phase A 依赖重试 WARN(刷屏收敛) + if VLogger._nowarn_register == 0: + VLogger.warning(fb, "PhaseA-DBG") # 回滚本文件已注册类的 MethodsEmitted:第 1 遍 _translate_oop_methods # 发射方法体前已置 MethodsEmitted=1(防重入),但方法体内跨模块调用 # 依赖 text.ll 未生成触发 _deps_pending → 本遍作废;若不回滚, @@ -982,13 +947,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, # 计时点 2:stub+text dump 及写盘完成;输出逐文件进度(对齐 Phase1 1b) t_pa2: t.CUInt64T = w32.win32base.GetTickCount64() - fb_pa: str = VLogger.fmt_buf() - if fb_pa is not None: - viperlib.snprintf(fb_pa, 1024, - "[%d/%d] PhaseA: %s (translate=%llu ms, dump=%llu ms, total=%llu ms)", - i + 1, file_count, ent.Path, - t_pa1 - t_pa0, t_pa2 - t_pa1, t_pa2 - t_pa0) - VLogger.info(fb_pa, "PhaseA") + viperlib.snprintf(fb, 1024, + "[%d/%d] PhaseA: %s (translate=%llu ms, dump=%llu ms, total=%llu ms)", + i + 1, file_count, ent.Path, + t_pa1 - t_pa0, t_pa2 - t_pa1, t_pa2 - t_pa0) + VLogger.info(fb, "PhaseA") done_flags[i] = 1 completed_this_pass += 1 @@ -1010,13 +973,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, ea_err: t.CUInt64T = t.CUInt64T(entries) + i_err * entry_size ent_err: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_err, t.CPtr)) if ent_err is not None and ent_err.Path is not None: - fb_err: str = VLogger.fmt_buf() - if fb_err is not None: - viperlib.snprintf(fb_err, 1024, - "Phase A 无法完成翻译: %s(请检查依赖模块是否已编译/注册;" - "缺失依赖明细见上方 PhaseA-DBG 警告,若被 --nowarn-register 抑制请去掉该参数重跑)", - ent_err.Path) - VLogger.error(fb_err, "PhaseA") + viperlib.snprintf(fb, 1024, + "Phase A 无法完成翻译: %s(请检查依赖模块是否已编译/注册;" + "缺失依赖明细见上方 PhaseA-DBG 警告,若被 --nowarn-register 抑制请去掉该参数重跑)", + ent_err.Path) + VLogger.error(fb, "PhaseA") stdlib.free(done_flags) VLogger.error("Phase A 多遍收敛失败,终止编译", "PhaseA") stdlib.free(entries) @@ -1032,8 +993,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, # === 3. Phase B: 编译每个文件为 .obj === if do_phase2 != 0: - if log is not None: - log.banner("Phase B: 编译 .obj") + log.banner("Phase B: 编译 .obj") # 收集 .obj 路径(增大到 64KB,避免 includes .obj 路径溢出导致链接丢失符号) # reachable_set/reachable_count: Phase B+ 填充,Phase C 用于按需链接 @@ -1074,17 +1034,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, # 组合本地 stub + 所有依赖 stub + 本地 text → 完整 IR combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE) if combined_ir is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path) - VLogger.error(fb, "PhaseB") + viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path) + VLogger.error(fb, "PhaseB") continue combined_len: t.CSizeT = StubMergerBuild.BuildCombinedIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE) if combined_len == 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "BuildCombinedIR 失败: %s", ent.Path) - VLogger.error(fb, "PhaseB") + viperlib.snprintf(fb, 1024, "BuildCombinedIR 失败: %s", ent.Path) + VLogger.error(fb, "PhaseB") stdlib.free(combined_ir) continue # 计时点 1:BuildCombinedIR 完成 @@ -1094,10 +1050,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, ret_w: int = BuildPipeline.write_ir_to_file(combined_ir, combined_len, temp_dir, ent.Sha1) stdlib.free(combined_ir) if ret_w != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "写 .ll 失败: %s", ent.Path) - VLogger.error(fb, "PhaseB") + viperlib.snprintf(fb, 1024, "写 .ll 失败: %s", ent.Path) + VLogger.error(fb, "PhaseB") sys.exit(1) # 计时点 2:写 .ll 完成 t_pb2: t.CUInt64T = w32.win32base.GetTickCount64() @@ -1111,10 +1065,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, t.CUInt64T(llc_tasks) + t.CSizeT(llc_task_count) * BuildPipeline.LlcTask.__sizeof__(), t.CPtr)) if BuildPipeline.init_llc_task(tslot, llc_ir_path, output_dir, ent.Sha1, cc_cmd, cc_flags) != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 任务构造失败: %s", ent.Path) - VLogger.error(fb, "PhaseB") + viperlib.snprintf(fb, 1024, "llc 任务构造失败: %s", ent.Path) + VLogger.error(fb, "PhaseB") sys.exit(1) # 计时点 3:llc 任务构造完成 t_pb3: t.CUInt64T = w32.win32base.GetTickCount64() @@ -1122,12 +1074,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, compiled_count += 1 # 显示已提交 llc 的文件(含三步计时:合并 stub / 写 .ll / 构造任务) - fb_comp: str = VLogger.fmt_buf() - if fb_comp is not None: - viperlib.snprintf(fb_comp, 1024, "[%d/%d] llc 已提交: %s (merge=%llu ms, write=%llu ms, task=%llu ms, total=%llu ms)", - i + 1, file_count, ent.Path, - t_pb1 - t_pb0, t_pb2 - t_pb1, t_pb3 - t_pb2, t_pb3 - t_pb0) - VLogger.info(fb_comp, "PhaseB") + viperlib.snprintf(fb, 1024, "[%d/%d] llc 已提交: %s (merge=%llu ms, write=%llu ms, task=%llu ms, total=%llu ms)", + i + 1, file_count, ent.Path, + t_pb1 - t_pb0, t_pb2 - t_pb1, t_pb3 - t_pb2, t_pb3 - t_pb0) + VLogger.info(fb, "PhaseB") # 构造 .obj 路径,检测是否是 main 模块(test_main.vp 或 main.vp,不再识别 .py) od_len: t.CSizeT = string.strlen(output_dir) is_main_mod: int = 0 @@ -1187,10 +1137,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, aret_as: int = BuildPipeline.asm_to_obj( ent_as.Path, ent_as.Sha1, output_dir, Config.TargetTriple) if aret_as != 0: - fb_asm_fail: str = VLogger.fmt_buf() - if fb_asm_fail is not None: - viperlib.snprintf(fb_asm_fail, 1024, "llvm-mc 汇编失败,终止编译: %s", ent_as.Path) - VLogger.error(fb_asm_fail, "PhaseB") + viperlib.snprintf(fb, 1024, "llvm-mc 汇编失败,终止编译: %s", ent_as.Path) + VLogger.error(fb, "PhaseB") sys.exit(1) obj_path_asm: str = StubMergerCollect._sliced_path(output_dir, od_len_as, ent_as.Sha1, "obj") if obj_path_asm is not None: @@ -1204,15 +1152,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, obj_paths[obj_pos] = '\0' stdlib.free(obj_path_asm) asm_compiled += 1 - fb_asm_ok: str = VLogger.fmt_buf() - if fb_asm_ok is not None: - viperlib.snprintf(fb_asm_ok, 1024, "[asm %d] 汇编完成: %s", asm_compiled, ent_as.Path) - VLogger.info(fb_asm_ok, "PhaseB") + viperlib.snprintf(fb, 1024, "[asm %d] 汇编完成: %s", asm_compiled, ent_as.Path) + VLogger.info(fb, "PhaseB") - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count) - VLogger.success(fb, "PhaseB") + viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count) + VLogger.success(fb, "PhaseB") if compiled_count == 0: VLogger.error("无成功编译的文件", "PhaseB") @@ -1228,12 +1172,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, td_len_mi: t.CSizeT = string.strlen(temp_dir) # 诊断日志:确认 Phase B+ 入口和 Sha1Store 状态 - fb_pbp_enter: str = VLogger.fmt_buf() - if fb_pbp_enter is not None: - viperlib.snprintf(fb_pbp_enter, 1024, - "PhaseB+ 入口: store_count=%d includes_binary_dir=%s", - StubMergerStore.GetSha1StoreCount(), includes_binary_dir) - VLogger.info(fb_pbp_enter, "PhaseB+") + viperlib.snprintf(fb, 1024, + "PhaseB+ 入口: store_count=%d includes_binary_dir=%s", + StubMergerStore.GetSha1StoreCount(), includes_binary_dir) + VLogger.info(fb, "PhaseB+") # 创建 includes_binary_dir 目录(确保 .obj 能写入和 collect_obj_files 能扫描) BuildPipeline.ensure_dir(includes_binary_dir) @@ -1251,10 +1193,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, string.memset(reachable_set, 0, REACHABLE_SET_SIZE) reachable_count = StubMergerBuild._BuildReachableSha1Set( mb, source_dir, temp_dir, reachable_set, app_deps_buf) - fb_reach: str = VLogger.fmt_buf() - if fb_reach is not None: - viperlib.snprintf(fb_reach, 1024, "可达 includes SHA1: %d 个", reachable_count) - VLogger.info(fb_reach, "PhaseB+") + viperlib.snprintf(fb, 1024, "可达 includes SHA1: %d 个", reachable_count) + VLogger.info(fb, "PhaseB+") # fast-fail: 可达集合构建失败(依赖未找到),永不回退,直接终止 if reachable_count < 0: VLogger.error("可达集合构建失败(fast-fail),终止编译", "PhaseB+") @@ -1282,10 +1222,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, store_rel_arr_mi: bytes = StubMergerStore.GetSha1StoreRelArrPtr() store_incdir_arr_mi: bytes = StubMergerStore.GetSha1StoreIncdirArrPtr() # 诊断:_BuildIncludesSha1Map 复制的条目数(PhaseB+ 循环执行前提) - fb_diag_scm: str = VLogger.fmt_buf() - if fb_diag_scm is not None: - viperlib.snprintf(fb_diag_scm, 1024, "诊断 store_count_mi=%d", store_count_mi) - VLogger.debug(fb_diag_scm, "PhaseB+") + viperlib.snprintf(fb, 1024, "诊断 store_count_mi=%d", store_count_mi) + VLogger.debug(fb, "PhaseB+") if store_count_mi > 0: # 拓扑排序可达 includes:被依赖模块先完整翻译。跨模块 vtable 生成 @@ -1301,21 +1239,17 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, reachable_set, reachable_count, topo_idx) # 诊断:拓扑排序条数(0 则循环不执行) - fb_diag_tc: str = VLogger.fmt_buf() - if fb_diag_tc is not None: - viperlib.snprintf(fb_diag_tc, 1024, "诊断 topo_count=%d reachable_count=%d", - topo_count, reachable_count) - VLogger.debug(fb_diag_tc, "PhaseB+") + viperlib.snprintf(fb, 1024, "诊断 topo_count=%d reachable_count=%d", + topo_count, reachable_count) + VLogger.debug(fb, "PhaseB+") # 诊断:dump reachable_set 内容(验证 BFS 写入的 sha1 是否有效) ri_dbg: int = 0 for ri_dbg in range(reachable_count): rsha1_dbg: str = reachable_set + t.CSizeT(ri_dbg) * 17 - fb_diag_rs: str = VLogger.fmt_buf() - if fb_diag_rs is not None: - viperlib.snprintf(fb_diag_rs, 1024, "诊断 reachable[%d]=%s", - ri_dbg, rsha1_dbg) - VLogger.debug(fb_diag_rs, "PhaseB+") + viperlib.snprintf(fb, 1024, "诊断 reachable[%d]=%s", + ri_dbg, rsha1_dbg) + VLogger.debug(fb, "PhaseB+") for si_mi in range(topo_count): # 当前条目(拓扑序索引,仅含可达模块) @@ -1357,11 +1291,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, continue # 诊断:obj 不存在,进入 is_decl 判定 - fb_diag_obj: str = VLogger.fmt_buf() - if fb_diag_obj is not None: - viperlib.snprintf(fb_diag_obj, 1024, "诊断 循环 si=%d ti=%d sha1=%s obj_exists=%d", - si_mi, ti, inc_sha1_mi, obj_exists_mi) - VLogger.debug(fb_diag_obj, "PhaseB+") + viperlib.snprintf(fb, 1024, "诊断 循环 si=%d ti=%d sha1=%s obj_exists=%d", + si_mi, ti, inc_sha1_mi, obj_exists_mi) + VLogger.debug(fb, "PhaseB+") # .obj 不存在,需要编译 # 构造源文件路径: {所属 includes 根目录}/{rel_path}(多目录逐条取 IncDir,空串回退 includes_dir) @@ -1416,11 +1348,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, tf_mi.close() stdlib.free(tpath_mi) # 诊断:is_decl 判定结果 - fb_diag_decl: str = VLogger.fmt_buf() - if fb_diag_decl is not None: - viperlib.snprintf(fb_diag_decl, 1024, "诊断 is_decl=%d src=%s", - is_decl_mi, src_fp_mi) - VLogger.debug(fb_diag_decl, "PhaseB+") + viperlib.snprintf(fb, 1024, "诊断 is_decl=%d src=%s", + is_decl_mi, src_fp_mi) + VLogger.debug(fb, "PhaseB+") # is_decl_mi == -1: text.ll 不存在(Phase1 未翻译此文件) # is_decl_mi == 1: 声明文件(仅 declare 无 define) # is_decl_mi == 0: 实现文件(有 define) @@ -1498,12 +1428,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, diag_text_ex = 1 df_diag_t.close() stdlib.free(diag_text) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, - "BuildCombinedIR 失败: %s (stub=%d text=%d is_decl=%d)", - src_fp_mi, diag_stub_ex, diag_text_ex, is_decl_mi) - VLogger.error(fb, "PhaseB+") + viperlib.snprintf(fb, 1024, + "BuildCombinedIR 失败: %s (stub=%d text=%d is_decl=%d)", + src_fp_mi, diag_stub_ex, diag_text_ex, is_decl_mi) + VLogger.error(fb, "PhaseB+") if inc_combined_mi is not None: stdlib.free(inc_combined_mi) stdlib.free(check_pat_mi) @@ -1519,18 +1447,14 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, stdlib.free(inc_combined_mi) if inc_cret_mi != 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 编译失败,终止编译: %s", src_fp_mi) - VLogger.error(fb, "PhaseB+") + viperlib.snprintf(fb, 1024, "llc 编译失败,终止编译: %s", src_fp_mi) + VLogger.error(fb, "PhaseB+") sys.exit(1) inc_compiled += 1 # 显示编译完成的 includes 文件 - fb_inc_comp: str = VLogger.fmt_buf() - if fb_inc_comp is not None: - viperlib.snprintf(fb_inc_comp, 1024, "[includes %d] 编译完成: %s", inc_compiled, src_fp_mi) - VLogger.info(fb_inc_comp, "PhaseB+") + viperlib.snprintf(fb, 1024, "[includes %d] 编译完成: %s", inc_compiled, src_fp_mi) + VLogger.info(fb, "PhaseB+") # 添加到 obj_paths (切片路径,从 includes_binary_dir 取) ibd_len_mi2: t.CSizeT = string.strlen(includes_binary_dir) @@ -1566,10 +1490,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, if store_mod_arr_mi is not None: stdlib.free(store_mod_arr_mi) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "编译缺失 includes: %d 个", inc_compiled) - VLogger.info(fb, "PhaseB+") + viperlib.snprintf(fb, 1024, "编译缺失 includes: %d 个", inc_compiled) + VLogger.info(fb, "PhaseB+") # 释放 app_deps_buf(Phase B+ 块未执行时此处兜底释放) if app_deps_buf is not None: @@ -1577,8 +1499,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, app_deps_buf = None # === 4. Phase C: 链接所有 .obj → .exe === - if log is not None: - log.banner("Phase C: 链接") + log.banner("Phase C: 链接") od_len2: t.CSizeT = string.strlen(output_dir) lo_len: t.CSizeT = string.strlen(linker_output) @@ -1672,10 +1593,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, fop_pos += op_len_p2 final_obj_paths[fop_pos] = '\0' elif StubMergerIR.IsDeclOnlyModule(temp_dir, td_len_pc, rsha1_pc) != 1: - fb_pc: str = VLogger.fmt_buf() - if fb_pc is not None: - viperlib.snprintf(fb_pc, 1024, "可达模块 .obj 缺失: %s", obj_path_pc) - VLogger.error(fb_pc, "PhaseC") + viperlib.snprintf(fb, 1024, "可达模块 .obj 缺失: %s", obj_path_pc) + VLogger.error(fb, "PhaseC") stdlib.free(obj_path_pc) final_obj_paths[fop_pos] = '\0' @@ -1693,26 +1612,18 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, None) if lret == 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "输出: %s", exe_path) - VLogger.success(fb, "PhaseC") + viperlib.snprintf(fb, 1024, "输出: %s", exe_path) + VLogger.success(fb, "PhaseC") if args.get_bool("run") and BuildPipeline._phase2_cmd_path is not None: # phase2command 模式:exe 尚未链接(命令在 bat 中),跳过 --run - fb_p2run: str = VLogger.fmt_buf() - if fb_p2run is not None: - viperlib.snprintf(fb_p2run, 1024, "phase2command 模式:跳过 --run(exe 尚未链接)") - VLogger.info(fb_p2run, "phase2cmd") + viperlib.snprintf(fb, 1024, "phase2command 模式:跳过 --run(exe 尚未链接)") + VLogger.info(fb, "phase2cmd") elif args.get_bool("run"): - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "执行: %s", exe_path) + viperlib.snprintf(fb, 1024, "执行: %s", exe_path) VLogger.info(fb, "run") rp: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False) if rp is not None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "退出码: %d", rp.returncode) + viperlib.snprintf(fb, 1024, "退出码: %d", rp.returncode) VLogger.info(fb, "run") else: VLogger.error("链接失败", "PhaseC") diff --git a/App/lib/Projectrans/Config.vp b/App/lib/Projectrans/Config.vp index 959bc9c..6940359 100644 --- a/App/lib/Projectrans/Config.vp +++ b/App/lib/Projectrans/Config.vp @@ -560,7 +560,7 @@ def get_includes_binary_dir() -> str: def print_config(): """打印当前配置""" - buf: str = VLogger.fmt_buf() + buf: str = VLogger.fmtbuffer if buf is None: return if ProjectName is not None: diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 1d94d06..5c1fd99 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -253,10 +253,8 @@ def _PyiTypeStr(buf: bytes, buf_size: t.CSizeT, pos: t.CSizeT, # BinOp.left 等回指祖先)时无限递归直至栈耗尽(Phase1 vpi 生成最先 # 执行,早于翻译阶段)。fail-fast 终止,不静默回退。 if depth > 64: - fb_pt: str = VLogger.fmt_buf() - if fb_pt is not None: - viperlib.snprintf(fb_pt, 256, "vpi 类型注解递归过深(AST 环或嵌套超过 64 层)") - VLogger.error(fb_pt, "StubGen") + viperlib.snprintf(VLogger.fmtbuffer, 256, "vpi 类型注解递归过深(AST 环或嵌套超过 64 层)") + VLogger.error(VLogger.fmtbuffer, "StubGen") sys.exit(1) if annot is None: return _PyiEmit(buf, buf_size, pos, "t.CInt") @@ -372,10 +370,8 @@ def _PyiDefaultStr(buf: bytes, buf_size: t.CSizeT, pos: t.CSizeT, """生成默认值表达式文本到 buf,返回新的 pos""" # 递归深度守卫:AST 损坏成自引用环时 fail-fast 终止(同 _PyiTypeStr) if depth > 64: - fb_pd: str = VLogger.fmt_buf() - if fb_pd is not None: - viperlib.snprintf(fb_pd, 256, "vpi 默认值表达式递归过深(AST 环或嵌套超过 64 层)") - VLogger.error(fb_pd, "StubGen") + viperlib.snprintf(VLogger.fmtbuffer, 256, "vpi 默认值表达式递归过深(AST 环或嵌套超过 64 层)") + VLogger.error(VLogger.fmtbuffer, "StubGen") sys.exit(1) if node is None: return pos diff --git a/App/lib/Stub/StubMerger/StubMergerBuild.vp b/App/lib/Stub/StubMerger/StubMergerBuild.vp index 01747fa..4de4c50 100644 --- a/App/lib/Stub/StubMerger/StubMergerBuild.vp +++ b/App/lib/Stub/StubMerger/StubMergerBuild.vp @@ -108,13 +108,12 @@ def _SeenInsert(tbl: bytes, cap: t.CSizeT, count: int, key: str, key_hash: t.CUI if tbl is None or key is None: return count kl: t.CSizeT = string.strlen(key) + fb: str = VLogger.fmtbuffer if kl >= _SEEN_NAME_MAX: return count if count >= cap: - fb_full: str = VLogger.fmt_buf() - if fb_full is not None: - viperlib.snprintf(fb_full, 1024, "已见符号表满(容量 %d),新增符号登记被丢弃——去重失效,必须增大容量", cap) - VLogger.error(fb_full, "StubMerger") + viperlib.snprintf(fb, 1024, "已见符号表满(容量 %d),新增符号登记被丢弃——去重失效,必须增大容量", cap) + VLogger.error(fb, "StubMerger") return count mask: t.CSizeT = cap - 1 idx: t.CSizeT = t.CSizeT(key_hash) & mask @@ -289,15 +288,14 @@ def _LoadAndAppendStub(temp_dir: str, td_len: t.CSizeT, dep_sha1: str, if dep_path is None: return out_pos df_ls: fileio.File | t.CPtr = fileio.File(dep_path, fileio.MODE.R) + fb: str = VLogger.fmtbuffer if df_ls.closed: stdlib.free(dep_path) # 依赖 stub 缺失:includes 映射内的模块缺失属编译错误(fail-fast), # 非映射模块(如 t/c 内部库、用户文件)按设计跳过 if StubMergerStore.LookupSha1RelPath(dep_sha1) is not None: - fb_ls: str = VLogger.fmt_buf() - if fb_ls is not None: - viperlib.snprintf(fb_ls, 1024, "依赖 stub 缺失: %s", dep_sha1) - VLogger.error(fb_ls, "StubMerger") + viperlib.snprintf(fb, 1024, "依赖 stub 缺失: %s", dep_sha1) + VLogger.error(fb, "StubMerger") return out_pos dep_br_ls: t.CInt64T = df_ls.read_all(dep_buf, StubMerger.STUB_READ_BUF_SIZE) df_ls.close() @@ -488,16 +486,15 @@ def _LoadAndAppendTextDeclares(temp_dir: str, td_len: t.CSizeT, dep_sha1: str, text_path: str = StubMergerCollect._sliced_path(temp_dir, td_len, dep_sha1, "text.ll") if text_path is None: return out_pos + fb: str = VLogger.fmtbuffer tf_lt: fileio.File | t.CPtr = fileio.File(text_path, fileio.MODE.R) if tf_lt.closed: stdlib.free(text_path) # 依赖 text 缺失:includes 映射内的模块缺失属编译错误(fail-fast), # 非映射模块(如 t/c 内部库、用户文件)按设计跳过 if StubMergerStore.LookupSha1RelPath(dep_sha1) is not None: - fb_lt: str = VLogger.fmt_buf() - if fb_lt is not None: - viperlib.snprintf(fb_lt, 1024, "依赖 text 缺失: %s", dep_sha1) - VLogger.error(fb_lt, "StubMerger") + viperlib.snprintf(fb, 1024, "依赖 text 缺失: %s", dep_sha1) + VLogger.error(fb, "StubMerger") return out_pos text_br: t.CInt64T = tf_lt.read_all(dep_buf, StubMerger.STUB_READ_BUF_SIZE) tf_lt.close() @@ -760,10 +757,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str, stdlib.free(sha1_arr) stdlib.free(mod_arr) return -1 - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "SHA1 映射: %d 个", map_count) - VLogger.debug(fb, "Reachable") + fb: str = VLogger.fmtbuffer + viperlib.snprintf(fb, 1024, "SHA1 映射: %d 个", map_count) + VLogger.debug(fb, "Reachable") # 工作列表(空格分隔的模块名) worklist: bytes = stdlib.malloc(StubMerger.REACH_WORKLIST_BUF) @@ -872,10 +868,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str, worklist[wl_len - 1] = '\0' wl_len -= 1 - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "源文件直接依赖: '%s'", worklist) - VLogger.debug(fb, "Reachable") + fb: str = VLogger.fmtbuffer + viperlib.snprintf(fb, 1024, "源文件直接依赖: '%s'", worklist) + VLogger.debug(fb, "Reachable") # 2.5. 预加入基础模块(builtins) # @@ -895,10 +890,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str, worklist[wl_len] = ' ' wl_len += 1 worklist[wl_len] = '\0' - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "预加入容器模块后: '%s'", worklist) - VLogger.debug(fb, "Reachable") + + viperlib.snprintf(fb, 1024, "预加入容器模块后: '%s'", worklist) + VLogger.debug(fb, "Reachable") # 3. 工作列表算法:递归收集可达 SHA1 processed: bytes = stdlib.malloc(StubMerger.REACH_WORKLIST_BUF) @@ -1030,10 +1024,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str, stdlib.free(app_mod_path) if is_app_src == 0: # fast-fail: includes 文件依赖未在内存中找到,Phase 1a-pre 未正确填充 - fb_ff: str = VLogger.fmt_buf() - if fb_ff is not None: - viperlib.snprintf(fb_ff, 1024, "依赖未找到 fast-fail: 模块 %s(sha1=%s) 的依赖未在内存中注册", mod_buf, found_sha1) - VLogger.error(fb_ff, "Reachable") + viperlib.snprintf(fb, 1024, "依赖未找到 fast-fail: 模块 %s(sha1=%s) 的依赖未在内存中注册", mod_buf, found_sha1) + VLogger.error(fb, "Reachable") stdlib.free(sha1_arr) stdlib.free(mod_arr) stdlib.free(worklist) @@ -1046,10 +1038,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str, stdlib.free(worklist) stdlib.free(processed) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "可达 SHA1: %d 个", reachable_count) - VLogger.debug(fb, "Reachable") + viperlib.snprintf(fb, 1024, "可达 SHA1: %d 个", reachable_count) + VLogger.debug(fb, "Reachable") return reachable_count # ============================================================ # BuildCombinedIR - 组合本地 stub + 依赖 stubs + 本地 text → 完整 IR @@ -1286,6 +1276,7 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str, # 2d. 验证 deps.txt 中所有依赖模块的 stub 文件都存在(fail-fast) # 避免到 llc 才报 undefined value 错误。 # 仅验证在 includes 映射中找到的模块(t/c 等内部库无 SHA1 映射,自动跳过)。 + fb: str = VLogger.fmtbuffer if deps_loaded != 0 and inc_count > 0: dep_total: t.CSizeT = string.strlen(deps_buf) dp: t.CSizeT = 0 @@ -1326,10 +1317,8 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str, if chk_path is not None: chk_f: fileio.File | t.CPtr = fileio.File(chk_path, fileio.MODE.R) if chk_f.closed: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "依赖模块 '%s' (sha1=%s) 的 stub 文件不存在: %s,立即终止编译", mod_nm, found_s, chk_path) - VLogger.error(fb, "BuildCombinedIR") + viperlib.snprintf(fb, 1024, "依赖模块 '%s' (sha1=%s) 的 stub 文件不存在: %s,立即终止编译", mod_nm, found_s, chk_path) + VLogger.error(fb, "BuildCombinedIR") chk_f.close() stdlib.free(chk_path) stdlib.free(mod_nm) @@ -1341,10 +1330,8 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str, tf: fileio.File | t.CPtr = fileio.File(text_path, fileio.MODE.R) if tf.closed: # 本地 text.ll 缺失:合并 IR 无法生成定义块,fail-fast 终止 - fb_tlp: str = VLogger.fmt_buf() - if fb_tlp is not None: - viperlib.snprintf(fb_tlp, 1024, "本地 text.ll 缺失: %s", text_path) - VLogger.error(fb_tlp, "StubMerger") + viperlib.snprintf(fb, 1024, "本地 text.ll 缺失: %s", text_path) + VLogger.error(fb, "StubMerger") stdlib.free(text_path) else: text_content: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE) diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index 1af2be6..02d647a 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -119,10 +119,8 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in StubMerger._sha1_store_incdir[idx_inc + StubMerger.MAX_INC_DIR_LEN - 1] = '\0' StubMerger._sha1_store_count += 1 if p_bad > 0: - fb_pbad: str = VLogger.fmt_buf() - if fb_pbad is not None: - viperlib.snprintf(fb_pbad, 1024, "includes SHA1 存储有 %d 个条目失败", p_bad) - VLogger.error(fb_pbad, "StubMerger") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "includes SHA1 存储有 %d 个条目失败", p_bad) + VLogger.error(VLogger.fmtbuffer, "StubMerger") return StubMerger._sha1_store_count # ============================================================ # AppendToSha1MapStore - 追加条目到全局 SHA1 映射存储器 diff --git a/App/lib/Stub/StubMerger/StubMergerTopo.vp b/App/lib/Stub/StubMerger/StubMergerTopo.vp index de059b5..bbf6b24 100644 --- a/App/lib/Stub/StubMerger/StubMergerTopo.vp +++ b/App/lib/Stub/StubMerger/StubMergerTopo.vp @@ -91,10 +91,8 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, rel_idx[rel_count] = i_t rel_count += 1 # 诊断:可达 store 索引数(rel_count=0 → topo_count=0 → PhaseB+ 循环不执行) - fb_rel: str = VLogger.fmt_buf() - if fb_rel is not None: - viperlib.snprintf(fb_rel, 1024, "诊断 topo rel_count=%d", rel_count) - VLogger.debug(fb_rel, "StubMergerTopo") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "诊断 topo rel_count=%d", rel_count) + VLogger.debug(VLogger.fmtbuffer, "StubMergerTopo") # 计算入度:m 在可达集合内的直接依赖数 i_r: int for i_r in range(rel_count): diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index d2c2daa..84c24eb 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -1486,6 +1486,9 @@ class AssignGenMixin: def translate_assign(self, trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: """翻译 Assign 语句,返回新增变量数(0 或 1)""" + + fb: str = VLogger.fmtbuffer + asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node) if asgn is None: VLogger.error("cast failed", "ASGN") @@ -1519,8 +1522,7 @@ class AssignGenMixin: if trans is not None and trans._deps_pending != 0: return 0 # 增强错误信息:包含文件名 + lineno + AST 节点详情,便于定位 - fb: str = VLogger.fmt_buf() - if fb is not None and asgn.value is not None: + if asgn.value is not None: sha1: str = trans.ModuleSha1 val_kind: int = asgn.value.kind() val_line: t.CInt = asgn.value.lineno @@ -1938,12 +1940,8 @@ class AssignGenMixin: mod_gv: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_module_var( trans.SymTab, nm.id) if mod_gv is not None: - fb_g: str = VLogger.fmt_buf() - msg_g: str = "global 声明缺失" - if fb_g is not None: - viperlib.snprintf(fb_g, 1024, "变量 '%s' 是模块级全局变量,函数内赋值需用 global 声明(否则创建局部变量遮蔽全局,导致全局保持 null 崩溃)", nm.id) - msg_g = fb_g - self.Gen.TypeGenErr.fatal_error(target, msg_g, "SyntaxError") + viperlib.snprintf(fb, 1024, "变量 '%s' 是模块级全局变量,函数内赋值需用 global 声明(否则创建局部变量遮蔽全局,导致全局保持 null 崩溃)", nm.id) + self.Gen.TypeGenErr.fatal_error(target, fb, "SyntaxError") # 普通局部变量 alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.get_or_create_sym( diff --git a/App/lib/core/Gen/CallGenCtor.vp b/App/lib/core/Gen/CallGenCtor.vp index 3792b67..a1c7bb1 100644 --- a/App/lib/core/Gen/CallGenCtor.vp +++ b/App/lib/core/Gen/CallGenCtor.vp @@ -428,6 +428,8 @@ class CallGenCtor(CallGenBase.CallGenBase): cargs: 参数 AST 列表 can: 参数数量 """ + fb: str = VLogger.fmtbuffer + if pool is None or builder is None or class_name is None: return None @@ -438,10 +440,8 @@ class CallGenCtor(CallGenBase.CallGenBase): if renum_entry is None: renum_entry = self.Gen.StructGen.find_struct(class_name) if renum_entry is None: - fb_re: str = VLogger.fmt_buf() - if fb_re is not None: - viperlib.snprintf(fb_re, 1024, "REnum construct: type %s not registered", class_name) - VLogger.error(fb_re, "RENUM") + viperlib.snprintf(fb, 1024, "REnum construct: type %s not registered", class_name) + VLogger.error(fb, "RENUM") return None renum_ty: llvmlite.LLVMType | t.CPtr = renum_entry.Ty diff --git a/App/lib/core/Gen/CallGenLeafKit.vp b/App/lib/core/Gen/CallGenLeafKit.vp index 8511167..f46c8d2 100644 --- a/App/lib/core/Gen/CallGenLeafKit.vp +++ b/App/lib/core/Gen/CallGenLeafKit.vp @@ -813,6 +813,8 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): cl: ast.Call | t.CPtr, trans: HT.Translator | t.CPtr = None) -> None: """翻译 print 调用(类型感知格式化 + 默认换行)""" + fb: str = VLogger.fmtbuffer + cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args if cargs is None: return @@ -841,10 +843,8 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if arg_val is None or arg_val.Ty is None: # fail-fast:print 参数翻译失败必须终止编译,绝不在格式串写 # 误导为数据问题而非编译器 bug。 - fb_pp: str = VLogger.fmt_buf() - if fb_pp is not None: - viperlib.snprintf(fb_pp, 1024, "print 参数翻译失败(表达式返回 None): [arg=%d]", ai) - VLogger.error(fb_pp, "PRINT") + viperlib.snprintf(fb, 1024, "print 参数翻译失败(表达式返回 None): [arg=%d]", ai) + VLogger.error(fb, "PRINT") self.Gen.TypeGenErr.fatal_error(arg, "print 参数翻译失败(表达式返回 None)", "TypeError") return diff --git a/App/lib/core/Gen/CallGenLib.vp b/App/lib/core/Gen/CallGenLib.vp index 3a0ecdf..62aedd4 100644 --- a/App/lib/core/Gen/CallGenLib.vp +++ b/App/lib/core/Gen/CallGenLib.vp @@ -312,7 +312,7 @@ class CallGenLib(CallGenBase.CallGenBase): # x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致 # WARNING: 未登记的外部函数返回类型默认推断为 i32,若实际返回指针/i64 会被截断 # --nowarn-register 可抑制此 WARN(自举编译中大量出现,刷屏影响日志收敛) - if VLogger.nowarn_register() == 0: + if VLogger._nowarn_register == 0: VLogger.warning( f"外部函数返回类型未登记,默认推断为 i32(可能截断指针/i64): {func_name}", "HandlesExprCall") diff --git a/App/lib/core/Gen/CallGenMixin.vp b/App/lib/core/Gen/CallGenMixin.vp index 9f51677..5d1f15a 100644 --- a/App/lib/core/Gen/CallGenMixin.vp +++ b/App/lib/core/Gen/CallGenMixin.vp @@ -771,9 +771,9 @@ class CallGenMixin(CallGenBase.CallGenBase): call_ret_ty = self.Gen.CallGenLib._infer_external_func_ret_ty(pool, func_name) # 如果模块中找不到函数,仅裸名调用(Name)才回退查局部变量(函数指针/ - # 闭包调用);模块属性调用(VLogger.fmt_buf())的目标是模块符号,绝不 - # 回退局部变量——跨模块任意同名可接受(CallGenLeafKit 局部 fmt_buf - # 曾劫持 VLogger.fmt_buf → 误走函数指针调用报 t.Callable 缺失), + # 闭包调用);模块属性调用(VLogger.fmtbuffer)的目标是模块符号,绝不 + # 回退局部变量——跨模块任意同名可接受(CallGenLeafKit 局部 fmtbuffer + # 曾劫持 VLogger.fmtbuffer → 误走函数指针调用报 t.Callable 缺失), # 仅 from-import 的裸名 yyy 与局部重名才可能冲突(该场景 func 是 Name)。 if found_func is None: fp_alloca: llvmlite.Value | t.CPtr = None @@ -1319,13 +1319,11 @@ class CallGenMixin(CallGenBase.CallGenBase): # 保持白名单类型继续,Phase A 多遍循环下遍重译—— # 届时依赖已生成 text.ll,可精确解析(治本:依赖先翻译)。 if self._dep_text_ll_exists(pool, cf_sha1) != 0: - cf_err: str = VLogger.fmt_buf() - if cf_err is not None: - viperlib.snprintf( - cf_err, 1024, - "跨模块函数 '%s' 返回类型无法精确获取(text.ll/vpi 均未命中)," - "默认 i32 会截断指针/i64,请检查依赖模块是否已编译/注册", call_name) - VLogger.error(cf_err, "HandlesExprCall") + viperlib.snprintf( + VLogger.fmtbuffer, 1024, + "跨模块函数 '%s' 返回类型无法精确获取(text.ll/vpi 均未命中)," + "默认 i32 会截断指针/i64,请检查依赖模块是否已编译/注册", call_name) + VLogger.error(VLogger.fmtbuffer, "HandlesExprCall") self.Gen.TypeGenErr.fatal_error( node, f"跨模块函数返回类型无法精确获取(text.ll/vpi 均未命中),默认 i32 会截断指针: {call_name}", @@ -1333,14 +1331,12 @@ class CallGenMixin(CallGenBase.CallGenBase): else: if trans is not None: trans._deps_pending = 1 - cf_dbg: str = VLogger.fmt_buf() - if cf_dbg is not None: viperlib.snprintf( - cf_dbg, 1024, + VLogger.fmtbuffer, 1024, "跨模块函数 '%s' 依赖模块 text.ll 尚未生成(Phase A 顺序)," "标记重试,本遍保持默认类型", call_name) - if VLogger.nowarn_register() == 0: - VLogger.warning(cf_dbg, "HandlesExprCall") + if VLogger._nowarn_register == 0: + VLogger.warning(VLogger.fmtbuffer, "HandlesExprCall") stdlib.free(cf_sha1) stdlib.free(cf_bare) # 跨模块调用:创建 declare 声明,避免 llc 报 undefined value diff --git a/App/lib/core/Gen/ClassGenDef.vp b/App/lib/core/Gen/ClassGenDef.vp index 23cf2ed..adf7c8b 100644 --- a/App/lib/core/Gen/ClassGenDef.vp +++ b/App/lib/core/Gen/ClassGenDef.vp @@ -421,10 +421,8 @@ class ClassGenDef(ClassGenBase.ClassGenBase): i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) if vtable_node is None: - fb_vn: str = VLogger.fmt_buf() - if fb_vn is not None: - viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name) - VLogger.error(fb_vn, "CLASS") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "failed to alloc vtable node for %s", class_name) + VLogger.error(VLogger.fmtbuffer, "CLASS") return 0 string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__()) vtable_node.Ty = i8_ptr_ty @@ -471,10 +469,8 @@ class ClassGenDef(ClassGenBase.ClassGenBase): # 创建 StructType(命名结构体) struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name) if struct_ty is None: - fb_st: str = VLogger.fmt_buf() - if fb_st is not None: - viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name) - VLogger.error(fb_st, "CLASS") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "failed to create StructType for %s", class_name) + VLogger.error(VLogger.fmtbuffer, "CLASS") return 0 # Phase 1b(declare_only=0)新注册的 struct_ty 会被注册到全局表并被后续文件 @@ -511,10 +507,8 @@ class ClassGenDef(ClassGenBase.ClassGenBase): entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.register_struct( pool, class_name, struct_ty, trans.ModuleSha1) if entry is None: - fb_re: str = VLogger.fmt_buf() - if fb_re is not None: - viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name) - VLogger.error(fb_re, "CLASS") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "failed to register %s", class_name) + VLogger.error(VLogger.fmtbuffer, "CLASS") return 0 # 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错) diff --git a/App/lib/core/Gen/ClassGenEnum.vp b/App/lib/core/Gen/ClassGenEnum.vp index 721293c..3b9c3cc 100644 --- a/App/lib/core/Gen/ClassGenEnum.vp +++ b/App/lib/core/Gen/ClassGenEnum.vp @@ -141,6 +141,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): if cd is None or cd.name is None or trans is None: return 0 + fb: str = VLogger.fmtbuffer pool: memhub.MemBuddy | t.CPtr = trans.Pool class_name: str = cd.name @@ -151,10 +152,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): children: list[ast.AST | t.CPtr] | t.CPtr = cd.children if children is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "ENUM") + viperlib.snprintf(fb, 1024, "%s has no body", class_name) + VLogger.warning(fb, "ENUM") return 0 cn: t.CSizeT = len(children) @@ -252,10 +251,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): member_count += 1 if member_count == 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no members", class_name) - VLogger.warning(fb, "ENUM") + viperlib.snprintf(fb, 1024, "%s has no members", class_name) + VLogger.warning(fb, "ENUM") return 0 # 确定基准类型:所有成员类型中 Bits 最大的 @@ -276,10 +273,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): entry: GenTypes.EnumEntry | t.CPtr = self.Gen.StmtGenDecl.register_enum( pool, class_name, base_ty) if entry is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to register %s", class_name) - VLogger.error(fb, "ENUM") + viperlib.snprintf(fb, 1024, "failed to register %s", class_name) + VLogger.error(fb, "ENUM") return 0 # 添加成员 @@ -297,12 +292,11 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): if mname is not None and mty2 is not None: self.Gen.StmtGenDecl.add_enum_member(pool, entry, mname, mval, mty2) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "registered %s with %d members, base_bits=%d", - class_name, member_count, max_bits) - VLogger.info(fb, "ENUM") + viperlib.snprintf(fb, 1024, "registered %s with %d members, base_bits=%d", + class_name, member_count, max_bits) + VLogger.info(fb, "ENUM") return 0 + def _get_type_size(self, ty: llvmlite.LLVMType | t.CPtr) -> int: """计算 LLVM 类型的字节大小(含对齐 padding)""" if ty is None: @@ -389,6 +383,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): def _translate_union_def(self, trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr) -> int: """翻译联合体定义,返回 0""" + fb: str = VLogger.fmtbuffer if cd is None or cd.name is None or trans is None: return 0 @@ -410,10 +405,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): children: list[ast.AST | t.CPtr] | t.CPtr = cd.children if children is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "UNION") + viperlib.snprintf(fb, 1024, "%s has no body", class_name) + VLogger.warning(fb, "UNION") return 0 cn: t.CSizeT = len(children) @@ -475,10 +468,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): field_count += 1 if field_count == 0: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no fields", class_name) - VLogger.warning(fb, "UNION") + viperlib.snprintf(fb, 1024, "%s has no fields", class_name) + VLogger.warning(fb, "UNION") return 0 if max_size < 1: @@ -506,10 +497,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): union_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, pnode, 1, union_type_name) if union_ty is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name) - VLogger.error(fb, "UNION") + viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name) + VLogger.error(fb, "UNION") return 0 # Phase 1b 新注册的 union struct_ty 深拷贝到 stdlib(跨文件 reset 存活) @@ -530,10 +519,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.register_struct( pool, class_name, union_ty, trans.ModuleSha1) if entry is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to register %s", class_name) - VLogger.error(fb, "UNION") + viperlib.snprintf(fb, 1024, "failed to register %s", class_name) + VLogger.error(fb, "UNION") return 0 # 标记为当前文件可见(命名空间隔离) @@ -556,11 +543,9 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): if fname is not None and fty2 is not None: self.Gen.StructGen.add_field(pool, entry, fname, fty2, None, None) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "registered %s with %d fields, max_size=%d", - class_name, field_count, max_size) - VLogger.info(fb, "UNION") + viperlib.snprintf(fb, 1024, "registered %s with %d fields, max_size=%d", + class_name, field_count, max_size) + VLogger.info(fb, "UNION") return 0 def _get_annotation_field_size(self, annotation: ast.AST | t.CPtr) -> int: """计算注解类型的字节大小,用于 REnum 布局计算""" @@ -623,6 +608,7 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): def _translate_renum_def(self, trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr) -> int: """翻译 REnum 类定义,返回 0""" + fb: str = VLogger.fmtbuffer if cd is None or cd.name is None or trans is None: return 0 @@ -642,10 +628,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): children: list[ast.AST | t.CPtr] | t.CPtr = cd.children if children is None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "RENUM") + viperlib.snprintf(fb, 1024, "%s has no body", class_name) + VLogger.warning(fb, "RENUM") return 0 cn: t.CSizeT = len(children) @@ -717,10 +701,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): variant_count += 1 if variant_count == 0: - fb2: str = VLogger.fmt_buf() - if fb2 is not None: - viperlib.snprintf(fb2, 1024, "%s has no variants", class_name) - VLogger.warning(fb2, "RENUM") + viperlib.snprintf(fb, 1024, "%s has no variants", class_name) + VLogger.warning(fb, "RENUM") return 0 # 计算每个位置的最大字段大小 @@ -773,10 +755,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): first_node = tail_node if first_node is None: - fb3: str = VLogger.fmt_buf() - if fb3 is not None: - viperlib.snprintf(fb3, 1024, "failed to build field list for %s", class_name) - VLogger.error(fb3, "RENUM") + viperlib.snprintf(fb, 1024, "failed to build field list for %s", class_name) + VLogger.error(fb, "RENUM") return 0 # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" @@ -790,10 +770,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): renum_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct( pool, first_node, total_positions, renum_type_name) if renum_ty is None: - fb4: str = VLogger.fmt_buf() - if fb4 is not None: - viperlib.snprintf(fb4, 1024, "failed to create type for %s", class_name) - VLogger.error(fb4, "RENUM") + viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name) + VLogger.error(fb, "RENUM") return 0 # Phase 1b 新注册的 REnum struct_ty 深拷贝到 stdlib(跨文件 reset 存活, @@ -812,10 +790,8 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.register_struct( pool, class_name, renum_ty, trans.ModuleSha1) if entry is None: - fb5: str = VLogger.fmt_buf() - if fb5 is not None: - viperlib.snprintf(fb5, 1024, "failed to register %s", class_name) - VLogger.error(fb5, "RENUM") + viperlib.snprintf(fb, 1024, "failed to register %s", class_name) + VLogger.error(fb, "RENUM") return 0 # 修复 class_name 指针不匹配: @@ -845,17 +821,16 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): # 注册变体字段名别名已在变体遍历时直接完成(避免 CSizeT→str 转换问题) - fb6: str = VLogger.fmt_buf() - if fb6 is not None: - viperlib.snprintf(fb6, 1024, "registered %s with %d variants, %d positions", - class_name, variant_count, total_positions) - VLogger.info(fb6, "RENUM") + viperlib.snprintf(fb, 1024, "registered %s with %d variants, %d positions", + class_name, variant_count, total_positions) + VLogger.info(fb, "RENUM") return 0 def _register_renum_variants(self, pool: memhub.MemBuddy | t.CPtr, class_name: str, cd: ast.ClassDef | t.CPtr, variant_count: int): """注册 REnum 类的变体名和 tag 值到全局变体表""" + fb: str = VLogger.fmtbuffer if pool is None or class_name is None or cd is None: return if variant_count == 0: @@ -886,25 +861,21 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): # ============ 临时诊断(0xb0 崩溃定位,定位后移除) ============ # lazy init 后 RenumClassNames 必非空;此时若 RCV 异常(null/小值) # 说明字段被越界覆盖或 __init__ 未生效,fail-fast 暴露崩溃现场。 - fb_diag: str = VLogger.fmt_buf() - if fb_diag is not None: - viperlib.snprintf(fb_diag, 1024, - "[RENUM-DIAG] self=%llu RN=%llu RCV=%llu RVN=%llu RVT=%llu RCount=%d class=%s", - t.CUInt64T(self), t.CUInt64T(self.RenumClassNames), - t.CUInt64T(self.RenumClassVariantCounts), - t.CUInt64T(self.RenumVariantNames), - t.CUInt64T(self.RenumVariantTags), - self.RenumClassCount, class_name) - VLogger.info(fb_diag, "RENUM") + viperlib.snprintf(fb, 1024, + "[RENUM-DIAG] self=%llu RN=%llu RCV=%llu RVN=%llu RVT=%llu RCount=%d class=%s", + t.CUInt64T(self), t.CUInt64T(self.RenumClassNames), + t.CUInt64T(self.RenumClassVariantCounts), + t.CUInt64T(self.RenumVariantNames), + t.CUInt64T(self.RenumVariantTags), + self.RenumClassCount, class_name) + VLogger.info(fb, "RENUM") rcv_chk: t.CUInt64T = t.CUInt64T(self.RenumClassVariantCounts) if rcv_chk == 0 or rcv_chk < 4096: - fb_fail: str = VLogger.fmt_buf() - if fb_fail is not None: - viperlib.snprintf(fb_fail, 1024, - "[RENUM-FAIL] RCV=%llu 异常(lazy init 后应为 perm_pool 地址),RenumClassCount=%d class=%s", - t.CUInt64T(self.RenumClassVariantCounts), - self.RenumClassCount, class_name) - VLogger.error(fb_fail, "RENUM") + viperlib.snprintf(fb, 1024, + "[RENUM-FAIL] RCV=%llu 异常(lazy init 后应为 perm_pool 地址),RenumClassCount=%d class=%s", + t.CUInt64T(self.RenumClassVariantCounts), + self.RenumClassCount, class_name) + VLogger.error(fb, "RENUM") stdlib.exit(1) # ============ 临时诊断结束 ============ @@ -937,11 +908,9 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): break if tag >= RENUM_VARIANT_PER_CLASS: # 每类固定 32 槽:变体超过上限继续写会越界污染相邻类槽,fail-fast 报错 - fb_rv: str = VLogger.fmt_buf() - if fb_rv is not None: - viperlib.snprintf(fb_rv, 1024, - "REnum 变体数超过上限 %d: %s", RENUM_VARIANT_PER_CLASS, class_name) - VLogger.error(fb_rv, "RENUM") + viperlib.snprintf(fb, 1024, + "REnum 变体数超过上限 %d: %s", RENUM_VARIANT_PER_CLASS, class_name) + VLogger.error(fb, "RENUM") break stmt: ast.AST | t.CPtr = children.get(ci) if stmt is None: diff --git a/App/lib/core/Gen/FuncGenDef.vp b/App/lib/core/Gen/FuncGenDef.vp index 5166c8a..744f849 100644 --- a/App/lib/core/Gen/FuncGenDef.vp +++ b/App/lib/core/Gen/FuncGenDef.vp @@ -488,10 +488,9 @@ class FuncGenDef(CallGenBase.CallGenBase): # 创建新的 LLVM 函数(使用 SHA1 混淆名) func = llvmlite.create_function(pool, mod, mangled_name, ret_ty) if func is None: - fb_cf: str = VLogger.fmt_buf() - if fb_cf is not None: - viperlib.snprintf(fb_cf, 1024, "create_function %s failed", fd.name) - VLogger.error(fb_cf, "FUNC") + fb: str = VLogger.fmtbuffer + viperlib.snprintf(fb, 1024, "create_function %s failed", fd.name) + VLogger.error(fb, "FUNC") return 0 # 提取 @c.Attribute 装饰器属性并设置到函数 diff --git a/App/lib/core/Gen/StmtGenDeclMixin.vp b/App/lib/core/Gen/StmtGenDeclMixin.vp index 622c7cd..c3ccc61 100644 --- a/App/lib/core/Gen/StmtGenDeclMixin.vp +++ b/App/lib/core/Gen/StmtGenDeclMixin.vp @@ -461,10 +461,8 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): return existing if self.EnumCount >= ENUM_MAX: - fb_et: str = VLogger.fmt_buf() - if fb_et is not None: - viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name) - VLogger.error(fb_et, "ENUM") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "table full, cannot register %s", name) + VLogger.error(VLogger.fmtbuffer, "ENUM") return None entry: GenTypes.EnumEntry | t.CPtr = self._get_enum_entry(self.EnumCount) @@ -524,10 +522,8 @@ class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): return ei_d if enum_entry.MemberCount >= ENUM_MEMBER_MAX: - fb_em: str = VLogger.fmt_buf() - if fb_em is not None: - viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name) - VLogger.error(fb_em, "ENUM") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "member table full for %s", enum_entry.Name) + VLogger.error(VLogger.fmtbuffer, "ENUM") return -1 idx: int = enum_entry.MemberCount diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index b2f0c79..1008461 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -190,10 +190,8 @@ class StructGenMixin: return existing if self.StructCount >= STRUCT_MAX: - fb_st: str = VLogger.fmt_buf() - if fb_st is not None: - viperlib.snprintf(fb_st, 1024, "table full, cannot register %s", name) - VLogger.error(fb_st, "STRUCT") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "table full, cannot register %s", name) + VLogger.error(VLogger.fmtbuffer, "STRUCT") return None entry: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(self.StructCount) @@ -289,10 +287,8 @@ class StructGenMixin: return -1 if struct_entry.FieldCount >= FIELD_MAX: - fb_sf: str = VLogger.fmt_buf() - if fb_sf is not None: - viperlib.snprintf(fb_sf, 1024, "field table full for %s", struct_entry.Name) - VLogger.error(fb_sf, "STRUCT") + viperlib.snprintf(VLogger.fmtbuffer, 1024, "field table full for %s", struct_entry.Name) + VLogger.error(VLogger.fmtbuffer, "STRUCT") return -1 idx: int = struct_entry.FieldCount @@ -764,6 +760,7 @@ class StructGenMixin: from_imports: from-import 映射("local:module" 格式),供模块限定名 的 import 别名(import X as Y → Y.Class)解析为模块 sha1 """ + fb: str = VLogger.fmtbuffer if class_name is None or field_name is None: return None @@ -828,34 +825,28 @@ class StructGenMixin: stdlib.free(mod_buf_q) return fe_q # 类命中但字段未找到:可读化报错(traceback 格式) - fb_qf: str = VLogger.fmt_buf() - if fb_qf is not None: - viperlib.snprintf(fb_qf, 1024, - "lookup_field_by_class: 类 '%s' 已按模块归属解析" - "(ModuleSha1=%s, FieldCount=%d)但字段 '%s' 未找到", - class_name, mod_sha1_q, mod_entry_q.FieldCount, field_name) - self.Gen.TypeGenErr.fatal_error(node, fb_qf, "AttributeError") + viperlib.snprintf(fb, 1024, + "lookup_field_by_class: 类 '%s' 已按模块归属解析" + "(ModuleSha1=%s, FieldCount=%d)但字段 '%s' 未找到", + class_name, mod_sha1_q, mod_entry_q.FieldCount, field_name) + self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError") stdlib.free(mod_buf_q) return None # 模块可解析但类未注册:fail-fast(暴露 vpi 注入/注册缺陷, # 不再裸名跨库抓其他模块同名类) - fb_qm: str = VLogger.fmt_buf() - if fb_qm is not None: - viperlib.snprintf(fb_qm, 1024, - "lookup_field_by_class: 类 '%s' 未找到(模块 '%s' 可解析" - " sha1=%s,但无同名注册类;请检查 vpi stub 注入或编译顺序)", - class_name, mod_buf_q, mod_sha1_q) - self.Gen.TypeGenErr.fatal_error(node, fb_qm, "AttributeError") + viperlib.snprintf(fb, 1024, + "lookup_field_by_class: 类 '%s' 未找到(模块 '%s' 可解析" + " sha1=%s,但无同名注册类;请检查 vpi stub 注入或编译顺序)", + class_name, mod_buf_q, mod_sha1_q) + self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError") stdlib.free(mod_buf_q) return None # 模块名未登记:fail-fast(不再裸名跨库回退) - fb_qs: str = VLogger.fmt_buf() - if fb_qs is not None: - viperlib.snprintf(fb_qs, 1024, - "lookup_field_by_class: 类 '%s' 的模块 '%s' 无法解析" - "(sha1 映射表未登记,请检查 import 与编译顺序)", - class_name, mod_buf_q) - self.Gen.TypeGenErr.fatal_error(node, fb_qs, "AttributeError") + viperlib.snprintf(fb, 1024, + "lookup_field_by_class: 类 '%s' 的模块 '%s' 无法解析" + "(sha1 映射表未登记,请检查 import 与编译顺序)", + class_name, mod_buf_q) + self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError") stdlib.free(mod_buf_q) return None stdlib.free(mod_buf_q) @@ -864,12 +855,10 @@ class StructGenMixin: entry = self.find_struct(class_name) if entry is None: # 诊断:目标类未注册(仿 Python traceback 格式,立即终止编译) - fb_lfbc: str = VLogger.fmt_buf() - if fb_lfbc is not None: - viperlib.snprintf(fb_lfbc, 1024, - "lookup_field_by_class: 类 '%s' 未注册 (struct_count=%d)", - class_name, self.StructCount) - self.Gen.TypeGenErr.fatal_error(node, fb_lfbc, "AttributeError") + viperlib.snprintf(fb, 1024, + "lookup_field_by_class: 类 '%s' 未注册 (struct_count=%d)", + class_name, self.StructCount) + self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError") return None # 先查找字段(诊断/error 之前返回,否则 error 立即退出导致查找永远失败) for fi in range(entry.FieldCount): @@ -909,7 +898,7 @@ class StructGenMixin: return rn_fe_l # 诊断:找到结构体但字段确实未找到 # 拼接注册字段列表(一行逗号分隔,供报错一眼定位) - # 注意:不能用 VLogger.fmt_buf()(与 fb_fields 同一静态缓冲,会被覆盖) + # 注意:不能用 VLogger.fmtbuffer(与 fb_fields 同一静态缓冲,会被覆盖) fb_flds_lst: str = stdlib.malloc(1024) if fb_flds_lst is not None: fb_flds_lst[0] = '\0' @@ -920,40 +909,39 @@ class StructGenMixin: string.strcat(fb_flds_lst, ", ") if string.strlen(fb_flds_lst) + string.strlen(fe.Name) < 1024: string.strcat(fb_flds_lst, fe.Name) - fb_fields: str = VLogger.fmt_buf() - if fb_fields is not None: - if rn_is_renum_l != 0: - # 报错友好化:REnum 类直接说明是"变体字段别名查找失败",并附 - # entry.Name 与别名槽位结果,一眼可辨"别名未注册"(槽位=-1) - # 还是"class_name 指针未统一"(已注册但传错指针查不到) - viperlib.snprintf(fb_fields, 1024, - "lookup_field_by_class: 类 '%s' 是 REnum 类(FieldCount=%d)," - "变体字段 '%s' 别名查找失败(entry.Name='%s',别名槽位=%d," - "请检查该变体字段是否已注册别名,或 class_name 指针是否统一)", - class_name, entry.FieldCount, field_name, rn_cls_l, rn_alias_l) - else: - # 可读化:附 entry.Name/ModuleSha1(跨模块同名定位)+ 注册字段 - # 列表 + 期望 sha1(调用方)→ 一眼分辨"跨模块同名类误匹配" - # vs "vpi stub 注入字段不全" vs "类定义与访问处不一致" - sha1_txt: str = "?" - if entry.ModuleSha1 is not None: - sha1_txt = entry.ModuleSha1 - want_sha1_txt: str = "?" - if sha1 is not None: - want_sha1_txt = sha1 - fld_lst_txt: str = "(无)" - if fb_flds_lst is not None and string.strlen(fb_flds_lst) > 0: - fld_lst_txt = fb_flds_lst - viperlib.snprintf(fb_fields, 1024, - "lookup_field_by_class: 类 '%s' 已注册 (FieldCount=%d, " - "entry.Name='%s', ModuleSha1=%s, 调用方期望 sha1=%s) " - "但字段 '%s' 未找到;注册字段: [%s]。可能原因: 跨模块同名类" - "被误匹配 / vpi stub 注入字段不全 / 类定义与访问处不一致", - class_name, entry.FieldCount, entry.Name, sha1_txt, - want_sha1_txt, field_name, fld_lst_txt) - # 仿 Python traceback 格式输出(Traceback 帧 + 文件:行号 + 错误类型), - # 立即终止编译(与 VLogger.error 同语义,格式对齐 fatal_error) - self.Gen.TypeGenErr.fatal_error(node, fb_fields, "AttributeError") + fb: str = VLogger.fmtbuffer + if rn_is_renum_l != 0: + # 报错友好化:REnum 类直接说明是"变体字段别名查找失败",并附 + # entry.Name 与别名槽位结果,一眼可辨"别名未注册"(槽位=-1) + # 还是"class_name 指针未统一"(已注册但传错指针查不到) + viperlib.snprintf(fb, 1024, + "lookup_field_by_class: 类 '%s' 是 REnum 类(FieldCount=%d)," + "变体字段 '%s' 别名查找失败(entry.Name='%s',别名槽位=%d," + "请检查该变体字段是否已注册别名,或 class_name 指针是否统一)", + class_name, entry.FieldCount, field_name, rn_cls_l, rn_alias_l) + else: + # 可读化:附 entry.Name/ModuleSha1(跨模块同名定位)+ 注册字段 + # 列表 + 期望 sha1(调用方)→ 一眼分辨"跨模块同名类误匹配" + # vs "vpi stub 注入字段不全" vs "类定义与访问处不一致" + sha1_txt: str = "?" + if entry.ModuleSha1 is not None: + sha1_txt = entry.ModuleSha1 + want_sha1_txt: str = "?" + if sha1 is not None: + want_sha1_txt = sha1 + fld_lst_txt: str = "(无)" + if fb_flds_lst is not None and string.strlen(fb_flds_lst) > 0: + fld_lst_txt = fb_flds_lst + viperlib.snprintf(fb, 1024, + "lookup_field_by_class: 类 '%s' 已注册 (FieldCount=%d, " + "entry.Name='%s', ModuleSha1=%s, 调用方期望 sha1=%s) " + "但字段 '%s' 未找到;注册字段: [%s]。可能原因: 跨模块同名类" + "被误匹配 / vpi stub 注入字段不全 / 类定义与访问处不一致", + class_name, entry.FieldCount, entry.Name, sha1_txt, + want_sha1_txt, field_name, fld_lst_txt) + # 仿 Python traceback 格式输出(Traceback 帧 + 文件:行号 + 错误类型), + # 立即终止编译(与 VLogger.error 同语义,格式对齐 fatal_error) + self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError") if fb_flds_lst is not None: stdlib.free(fb_flds_lst) # 诊断:找到结构体但字段未找到 diff --git a/App/lib/core/Gen/TypeGenCType.vp b/App/lib/core/Gen/TypeGenCType.vp index 90d46b4..39e482f 100644 --- a/App/lib/core/Gen/TypeGenCType.vp +++ b/App/lib/core/Gen/TypeGenCType.vp @@ -329,14 +329,12 @@ class TypeGenCType(TypeGenBase.TypeGenBase): self.ConstEvalOk = 1 return x_val # 定位日志:跨模块 CDefine 查找失败(t.CArray count 场景) - fb_cdf: str = VLogger.fmt_buf() - if fb_cdf is not None: - viperlib.snprintf(fb_cdf, 1024, - "[CDEF-MISS] name=%s fi=%s im=%s", - nm.id, - from_imports if from_imports is not None else "(null)", - imported_modules if imported_modules is not None else "(null)") - VLogger.error(fb_cdf, "CDEF") + viperlib.snprintf(VLogger.fmtbuffer, 1024, + "[CDEF-MISS] name=%s fi=%s im=%s", + nm.id, + from_imports if from_imports is not None else "(null)", + imported_modules if imported_modules is not None else "(null)") + VLogger.error(VLogger.fmtbuffer, "CDEF") self.ConstEvalOk = 0 return 0 self.ConstEvalOk = 1 diff --git a/App/lib/core/IncludesScanner.vp b/App/lib/core/IncludesScanner.vp index 7b8aa4e..e39047c 100644 --- a/App/lib/core/IncludesScanner.vp +++ b/App/lib/core/IncludesScanner.vp @@ -210,6 +210,8 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr, # 子目录递归失败计数(不静默忽略,汇总处 fail-fast 终止) subdir_failed: int = 0 + fb: str = VLogger.fmtbuffer + # 构造搜索模式: root_dir/* root_len: t.CSizeT = string.strlen(root_dir) pattern: bytes = stdlib.malloc(root_len + 4) @@ -294,15 +296,11 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr, sha1: str = compute_file_sha1(pool, full_path) if sha1 is not None: add_file_entry(result, pool, full_path, rel_path, sha1, inc_dir) - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "扫描: %s -> %s", rel_path, sha1) - VLogger.debug(fb, "scan") + viperlib.snprintf(fb, 1024, "扫描: %s -> %s", rel_path, sha1) + VLogger.debug(fb, "scan") else: - fb_sha: str = VLogger.fmt_buf() - if fb_sha is not None: - viperlib.snprintf(fb_sha, 1024, "SHA1 计算失败: %s", full_path) - VLogger.warning(fb_sha, "scan") + viperlib.snprintf(fb, 1024, "SHA1 计算失败: %s", full_path) + VLogger.warning(fb, "scan") # 继续搜索下一个文件 if win32file.FindNextFileA(handle, find_data) == 0: @@ -310,10 +308,8 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr, win32file.FindClose(handle) if subdir_failed > 0: - fb_sdf: str = VLogger.fmt_buf() - if fb_sdf is not None: - viperlib.snprintf(fb_sdf, 1024, "子目录扫描失败 %d 个", subdir_failed) - VLogger.error(fb_sdf, "scan") + viperlib.snprintf(fb, 1024, "子目录扫描失败 %d 个", subdir_failed) + VLogger.error(fb, "scan") return 0 diff --git a/App/lib/core/VLogger.vp b/App/lib/core/VLogger.vp index 3393e39..7bb3b1b 100644 --- a/App/lib/core/VLogger.vp +++ b/App/lib/core/VLogger.vp @@ -191,47 +191,23 @@ class Logger: _mbuddy: memhub.MemBuddy | t.CPtr # 全局 logger 指针 -_g_logger: Logger | t.CPtr +logger: Logger | t.CPtr +log: Logger | t.CPtr # 全局格式化缓冲区(用于带变量的日志消息,1024 字节) -_fmt_buf: str +fmtbuffer: str - -def fmt_buf() -> str: - """获取全局格式化缓冲区(1024 字节)。 - - 用法: - buf: str = VLogger.fmt_buf() - if buf is not None: - viperlib.snprintf(buf, 1024, "翻译: %s (sha1=%s)", rp, sha1) - log.info(buf, "Phase1") - """ - global _fmt_buf - if _fmt_buf is None: - _fmt_buf = stdlib.malloc(1024) - return _fmt_buf - - -def get_logger() -> Logger | t.CPtr: - """获取全局 logger 实例。若不存在则通过 _mbuddy 分配并初始化。""" - global _g_logger - if _g_logger is None: - if _mbuddy is None: - return None - raw: t.CVoid | t.CPtr = _mbuddy.alloc(Logger.__sizeof__()) - if raw is None: - return None - _g_logger = raw - _g_logger.__before_init__() - _g_logger.__init__(LogLevel.INFO) - return _g_logger - - -def set_logger(logger: Logger | t.CPtr) -> int: - """设置全局 logger 实例。""" - global _g_logger - _g_logger = logger - return 0 +def init_logger(): + """初始化全局 logger 实例。""" + global logger, log, fmtbuffer + raw: t.CVoid | t.CPtr = _mbuddy.alloc(Logger.__sizeof__()) + # if raw is None: return None 存疑,如何去管理内存? + logger = raw + logger.__before_init__() + logger.__init__(LogLevel.INFO) + log = logger + fmtbuffer = _mbuddy.alloc(1024) + # if fmtbuffer is None: return None # ============================================================ @@ -240,19 +216,7 @@ def set_logger(logger: Logger | t.CPtr) -> int: # 下遍重试"(PhaseA-DBG)。自举编译中大量出现,刷屏影响日志收敛。 # 仅抑制输出,不影响内部逻辑(默认 i32 推断、标记重试等照常执行)。 # ============================================================ -_nowarn_register_flag: t.CInt = 0 - - -def set_nowarn_register(flag: int) -> None: - """设置 --nowarn-register(1=抑制 Phase A 依赖类 WARN 输出)""" - global _nowarn_register_flag - _nowarn_register_flag = flag - - -def nowarn_register() -> int: - """查询 --nowarn-register 开关状态(1=抑制)""" - return _nowarn_register_flag - +_nowarn_register: int = 0 # ============================================================ # 模块级便捷函数(与 TPC 的 lib.core.VLogger 对齐) @@ -263,21 +227,18 @@ def nowarn_register() -> int: def info(msg: str, category: str = "") -> int: """输出 INFO 级别日志。""" - log: Logger | t.CPtr = get_logger() if log is not None: return log.info(msg, category) return 0 def warning(msg: str, category: str = "") -> int: """输出 WARN 级别日志。""" - log: Logger | t.CPtr = get_logger() if log is not None: return log.warning(msg, category) return 0 def error(msg: str, category: str = "") -> int: """输出 ERROR 级别日志并立即终止进程。""" - log: Logger | t.CPtr = get_logger() if log is not None: return log.error(msg, category) # logger 不可用时也直接退出 sys.exit(1) @@ -286,20 +247,17 @@ def error(msg: str, category: str = "") -> int: def success(msg: str, category: str = "") -> int: """输出 SUCCESS 级别日志。""" - log: Logger | t.CPtr = get_logger() if log is not None: return log.success(msg, category) return 0 def critical(msg: str, category: str = "") -> int: """输出 CRITICAL 级别日志(致命错误,红底白字)。""" - log: Logger | t.CPtr = get_logger() if log is not None: return log.critical(msg, category) return 0 def debug(msg: str, category: str = "") -> int: """输出 DEBUG 级别日志。""" - log: Logger | t.CPtr = get_logger() if log is not None: return log.debug(msg, category) return 0 diff --git a/App/main.vp b/App/main.vp index 64179f7..a839747 100644 --- a/App/main.vp +++ b/App/main.vp @@ -42,12 +42,12 @@ CODE_PAGE: t.CDefine = 65001 # Source code buffer size (1MB) SRC_BUF_SIZE: t.CDefine = 1048576 # Version (dev/beta/rc) -V_VIPER_VERSION: t.CDefine = "1.0.3-dev.30 2026-07-27 Non-LTS" -V_TPV_VERSION: t.CDefine = "0.0.3-dev.230" -V_RUNTIME_VERSION: t.CDefine = "0.2.2+4-Non-LTS" -V_TPC_COMMIT: t.CDefine = "1dc23ffdde" -V_TPV_COMMIT: t.CDefine = "f4fee79d4d" -V_RUNTIME_COMMIT: t.CDefine = "4ce6095359" +V_VIPER_VERSION: t.CDefine = "1.0.3-dev.31 2026-07-27 Non-LTS" +V_TPV_VERSION: t.CDefine = "0.0.3-dev.428" +V_RUNTIME_VERSION: t.CDefine = "0.2.3+19-Non-LTS" +V_TPC_COMMIT: t.CDefine = "e376b949c9" +V_TPV_COMMIT: t.CDefine = "ab0f37e1a8" +V_RUNTIME_COMMIT: t.CDefine = "f087aa88e2" V_TARGET: t.CDefine = "x86_64-w64-windows-gnu" V_LLVM: t.CDefine = "22.1.8" @@ -128,9 +128,11 @@ def main() -> int: # P6: 注入语句/赋值/变量/导入/翻译驱动模块的单例 # 初始化 VLogger 并打印启动日志 - log: VLogger.Logger | t.CPtr = VLogger.get_logger() + VLogger.init_logger() + log: VLogger.Logger | t.CPtr = VLogger.logger if log is None: log.error("TransPyV Failed to parse parameters") + fmtbuf: str = VLogger.fmtbuffer # 初始化命令行参数(Windows: GetCommandLineA, POSIX: /proc/self/cmdline) sys._init_argv() @@ -153,6 +155,7 @@ def main() -> int: parser.add_argument("--phase2command", None, argparse.STRING, 0, None, False, argparse.STORE, "Do not run llc/link: write Phase2 llc(opt+llc) and clang link commands to the given .bat path") parser.add_argument("--nowarn-register", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Suppress Phase A dependency WARN") parser.add_argument("--detection", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Enable MemBuddy allocation detection (0xCDCD markers + record-table probe for out-of-bounds writes; applies to both mb and perm_pool)") + parser.add_argument("--show-args", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show all parsed arguments") parser.add_argument("--build-dir", None, argparse.STRING, 0, None, False, argparse.STORE, "Override project.vpj build_dir (default ./.tpv_build; relative paths resolve against the project dir)") parser.add_argument("--version", "-v", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show version and exit") parser.add_argument("--help", "-h", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show help and exit") @@ -160,8 +163,7 @@ def main() -> int: # 解析命令行参数 args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv) if args is None: - if log is not None: - log.error("参数解析失败", "argparse") + log.error("参数解析失败", "argparse") return 1 if args.get_bool("help"): @@ -185,40 +187,40 @@ Target: %s return 0 # 打印解析结果 - #if log is not None: - # log.banner("TransPyV 参数解析结果") + # log.banner("TransPyV 参数解析结果") # 字符串参数 - project: str = args.get_str("project") - src: str = args.get_str("src") - temp: str = args.get_str("temp") - output: str = args.get_str("output") - phase: str = args.get_str("phase") - cc: str = args.get_str("cc") - build_dir: str = args.get_str("build-dir") - _gb_clean: INT = args.get_bool("clean") - #if project is not None: stdio.printf(" --project: %s\n", project) - #else: stdio.printf(" --project: (未指定)\n") - #if src is not None: stdio.printf(" --src: %s\n", src) - #else: stdio.printf(" --src: (未指定)\n") - #if temp is not None: stdio.printf(" --temp: %s\n", temp) - #else: stdio.printf(" --temp: (未指定)\n") - #if output is not None: stdio.printf(" --output: %s\n", output) - #else: stdio.printf(" --output: (未指定)\n") - #if phase is not None: stdio.printf(" --phase: %s\n", phase) - #else: stdio.printf(" --phase: (未指定,默认 all)\n") - #if cc is not None: stdio.printf(" --cc: %s\n", cc) - #else: stdio.printf(" --cc: (未指定)\n") - #if _gb_clean: stdio.printf(" --clean: True\n") - #else: stdio.printf(" --clean: False\n") - #if args.get_bool("run"): stdio.printf(" --run: True\n") - #else: stdio.printf(" --run: False\n") - #if args.get_bool("rebuild-includes"): stdio.printf(" --rebuild-includes: True\n") - #else: stdio.printf(" --rebuild-includes: False\n") - #if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n") - #else: stdio.printf(" --clear-cache: False\n") - - #stdio.printf("\n参数解析完成。\n") + project: str = args.get_str("project") + src: str = args.get_str("src") + temp: str = args.get_str("temp") + output: str = args.get_str("output") + phase: str = args.get_str("phase") + cc: str = args.get_str("cc") + build_dir: str = args.get_str("build-dir") + _gb_clean: bool = args.get_bool("clean") + show_args: bool = args.get_bool("show-args") + if show_args: + if project is not None: stdio.printf(" --project: %s\n", project) + else: stdio.printf(" --project: (未指定)\n") + if src is not None: stdio.printf(" --src: %s\n", src) + else: stdio.printf(" --src: (未指定)\n") + if temp is not None: stdio.printf(" --temp: %s\n", temp) + else: stdio.printf(" --temp: (未指定)\n") + if output is not None: stdio.printf(" --output: %s\n", output) + else: stdio.printf(" --output: (未指定)\n") + if phase is not None: stdio.printf(" --phase: %s\n", phase) + else: stdio.printf(" --phase: (未指定,默认 all)\n") + if cc is not None: stdio.printf(" --cc: %s\n", cc) + else: stdio.printf(" --cc: (未指定)\n") + if _gb_clean: stdio.printf(" --clean: True\n") + else: stdio.printf(" --clean: False\n") + if args.get_bool("run"): stdio.printf(" --run: True\n") + else: stdio.printf(" --run: False\n") + if args.get_bool("rebuild-includes"): stdio.printf(" --rebuild-includes: True\n") + else: stdio.printf(" --rebuild-includes: False\n") + if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n") + else: stdio.printf(" --clear-cache: False\n") + stdio.printf("参数解析完成。\n\n") # ASan 模式 # includes 缓存用独立目录 .binary_asan 隔离 asan 插桩 obj,避免与非 asan obj 混链 @@ -226,17 +228,15 @@ Target: %s if args.get_bool("asan"): BuildPipeline._asan_mode = True Config._inc_bin_suffix = ".binary_asan" - if log is not None: - log.info("ASan 模式已启用(opt -passes=asan + libclang_rt)", "asan") + log.info("ASan 模式已启用(opt -passes=asan + libclang_rt)", "asan") # ASan 模式清理 asan includes 缓存(强制重建 asan 插桩 obj) mf_inc_bin_asan: str = Config.get_includes_binary_dir() if mf_inc_bin_asan is not None: n_asan: int = Utils.CleanDir(mf_inc_bin_asan) - if log is not None: - fb_asan: str = VLogger.fmt_buf() - if fb_asan is not None: - viperlib.snprintf(fb_asan, 1024, "ASan 模式清理 includes 缓存: %d 个文件(将重建 asan obj)", n_asan) - log.info(fb_asan, "asan") + fb_asan: str = VLogger.fmtbuffer + if fb_asan is not None: + viperlib.snprintf(fb_asan, 1024, "ASan 模式清理 includes 缓存: %d 个文件(将重建 asan obj)", n_asan) + log.info(fb_asan, "asan") else: BuildPipeline._asan_mode = False Config._inc_bin_suffix = ".binary" @@ -247,34 +247,25 @@ Target: %s p2c: str = args.get_str("phase2command") if p2c is not None: BuildPipeline._phase2_cmd_path = p2c - if log is not None: - fb_p2c: str = VLogger.fmt_buf() - if fb_p2c is not None: - viperlib.snprintf(fb_p2c, 1024, "--phase2command: 不执行 llc/链接,命令写入 %s", p2c) - log.info(fb_p2c, "phase2cmd") + viperlib.snprintf(fmtbuf, 1024, "--phase2command: 不执行 llc/链接,命令写入 %s", p2c) + log.info(fmtbuf, "phase2cmd") # --nowarn-register:抑制"外部函数返回类型未登记"类 WARN 输出 if args.get_bool("nowarn-register"): - VLogger.set_nowarn_register(1) - if log is not None: - log.info("--nowarn-register 已启用:抑制注册类 WARN 输出", "vlogger") + VLogger._nowarn_register = 1 + log.info("--nowarn-register 已启用:抑制注册类 WARN 输出", "vlogger") # 加载 project.vpj 配置 proj_loaded: int = 0 proj_path: str = project if proj_path is not None: - if log is not None: - log.banner("工程配置") + log.banner("工程配置") cfg_ret: int = Config.Load_project_config(proj_path) if cfg_ret == 0: proj_loaded = 1 else: - if log is not None: - warn_buf: str = stdlib.malloc(256) - if warn_buf is not None: - viperlib.snprintf(warn_buf, 256, "无法加载 project.vpj: %s", proj_path) - log.warning(warn_buf, "config") - stdlib.free(warn_buf) + viperlib.snprintf(fmtbuf, 256, "无法加载 project.vpj: %s", proj_path) + log.warning(fmtbuf, "config") else: # 尝试默认路径 project.vpj(当前目录和上级目录) proj_path = "project.vpj" @@ -310,58 +301,40 @@ Target: %s # === --clean: 清理 temp、output 和 includes.binary 目录 === if _gb_clean: - if log is not None: - log.info("清理临时目录...", "clean") + log.info("清理临时目录...", "clean") if Config.TempDir is not None: n: int = Utils.CleanDir(Config.TempDir) - if log is not None: - fb: str = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s: 删除 %d 个文件", Config.TempDir, n) - log.info(fb, "clean") + viperlib.snprintf(fmtbuf, 1024, "%s: 删除 %d 个文件", Config.TempDir, n) + log.info(fmtbuf, "clean") if Config.OutputDir is not None: n2: int = Utils.CleanDir(Config.OutputDir) - if log is not None: - fb2: str = VLogger.fmt_buf() - if fb2 is not None: - viperlib.snprintf(fb2, 1024, "%s: 删除 %d 个文件", Config.OutputDir, n2) - log.info(fb2, "clean") + viperlib.snprintf(fmtbuf, 1024, "%s: 删除 %d 个文件", Config.OutputDir, n2) + log.info(fmtbuf, "clean") # 清理 includes.binary 目录(旧 .obj 文件会导致跳过重新编译) mf_inc_bin_clean: str = Config.get_includes_binary_dir() if mf_inc_bin_clean is not None: n3: int = Utils.CleanDir(mf_inc_bin_clean) - if log is not None: - fb3: str = VLogger.fmt_buf() - if fb3 is not None: - viperlib.snprintf(fb3, 1024, "%s: 删除 %d 个文件", mf_inc_bin_clean, n3) - log.info(fb3, "clean") + viperlib.snprintf(fmtbuf, 1024, "%s: 删除 %d 个文件", mf_inc_bin_clean, n3) + log.info(fmtbuf, "clean") # === --rebuild-includes: 删除 includes.binary 预编译缓存 === # 强制下次编译时重新编译所有 includes(不清 temp/output) if args.get_bool("rebuild-includes"): - if log is not None: - log.info("重建 includes 缓存...", "rebuild-includes") + log.info("重建 includes 缓存...", "rebuild-includes") mf_inc_bin_rb: str = Config.get_includes_binary_dir() if mf_inc_bin_rb is not None: n_rb: int = Utils.CleanDir(mf_inc_bin_rb) - if log is not None: - fb_rb: str = VLogger.fmt_buf() - if fb_rb is not None: - viperlib.snprintf(fb_rb, 1024, "%s: 删除 %d 个文件(includes 将重新编译)", mf_inc_bin_rb, n_rb) - log.info(fb_rb, "rebuild-includes") + viperlib.snprintf(fmtbuf, 1024, "%s: 删除 %d 个文件(includes 将重新编译)", mf_inc_bin_rb, n_rb) + log.info(fmtbuf, "rebuild-includes") # === --clear-cache: 清除 temp 目录缓存(.vpi/.stub.ll/.text.ll) === # 强制下次 Phase1 重新生成 stub(不清 output/includes.binary) if args.get_bool("clear-cache"): - if log is not None: - log.info("清除 temp 缓存...", "clear-cache") + log.info("清除 temp 缓存...", "clear-cache") if Config.TempDir is not None: n_cc: int = Utils.CleanDir(Config.TempDir) - if log is not None: - fb_cc: str = VLogger.fmt_buf() - if fb_cc is not None: - viperlib.snprintf(fb_cc, 1024, "%s: 删除 %d 个文件(.vpi/.stub.ll 缓存)", Config.TempDir, n_cc) - log.info(fb_cc, "clear-cache") + viperlib.snprintf(fmtbuf, 1024, "%s: 删除 %d 个文件(.vpi/.stub.ll 缓存)", Config.TempDir, n_cc) + log.info(fmtbuf, "clear-cache") # === --phase 参数控制 === # phase=1: 仅 stub 分离(生成 .stub.ll/.text.ll),不编译 @@ -377,11 +350,8 @@ Target: %s do_phase1 = 1 if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0: do_phase2 = 1 - if log is not None: - fb3: str = VLogger.fmt_buf() - if fb3 is not None: - viperlib.snprintf(fb3, 1024, "模式: %s (phase1=%d phase2=%d)", phase_mode, do_phase1, do_phase2) - log.info(fb3, "phase") + viperlib.snprintf(fmtbuf, 1024, "模式: %s (phase1=%d phase2=%d)", phase_mode, do_phase1, do_phase2) + log.info(fmtbuf, "phase") # === Phase1: 扫描 includes(按需翻译)=== # 对 includes 目录中每个 .vp/.py 文件,若 stub 不存在则翻译并分离 stub @@ -394,8 +364,7 @@ Target: %s return 1 # 如果仅 Phase1(不执行 Phase2),直接退出 if do_phase2 == 0: - if log is not None: - log.info("Phase1 完成,退出", "phase") + log.info("Phase1 完成,退出", "phase") return 0 # AST 解析:如果指定了 --src 或 --project,读取文件并解析为 AST 树 @@ -406,21 +375,20 @@ Target: %s # 未初始化的 Config 字段可能为垃圾指针 → is not None 检查通过 → # 用非法路径 → 崩溃且 ASan 堆栈来不及输出) if proj_loaded == 0 and src_path is None: - if log is not None: - log.error("未找到 project.vpj(当前目录/上级目录)且未指定 --src,无法构建", "config") + log.error("未找到 project.vpj(当前目录/上级目录)且未指定 --src,无法构建", "config") argparse.release(args) return 1 # === 多文件项目模式 === # 当 --project 指定但 --src 未指定时,扫描 source_dir 下所有 .vp/.py 文件编译 if src_path is None and project is not None and Config.SourceDir is not None: - mf_temp: str = Config.TempDir if Config.TempDir is not None else "." - mf_output: str = Config.OutputDir if Config.OutputDir is not None else "." - mf_cc: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc" - mf_cc_flags: str = Config.CompilerFlags if Config.CompilerFlags is not None else "-filetype=obj -relocation-model=pic" - mf_linker: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++" + mf_temp: str = Config.TempDir if Config.TempDir is not None else "." + mf_output: str = Config.OutputDir if Config.OutputDir is not None else "." + mf_cc: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc" + mf_cc_flags: str = Config.CompilerFlags if Config.CompilerFlags is not None else "-filetype=obj -relocation-model=pic" + mf_linker: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++" mf_linker_flags: str = Config.LinkerFlags if Config.LinkerFlags is not None else "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition" - mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe" + mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe" mf_includes_bin: str = Config.get_includes_binary_dir() mf_ret: int = Phase2.RunMultiFileProject( @@ -428,8 +396,7 @@ Target: %s mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out, mf_includes_bin, Config.IncludesDirs, do_phase1, do_phase2, log, args) argparse.release(args) - if log is not None: - log.success("TransPyV 完成") + log.success("TransPyV 完成") return mf_ret # === 单文件模式:--src 指定时使用指定文件;--project 但无 SourceDir 时回退 === @@ -441,29 +408,22 @@ Target: %s if path_buf is not None: viperlib.snprintf(path_buf, sd_len + 16, "%s/main.vp", Config.SourceDir) src_path = path_buf - if log is not None: - fb4: str = VLogger.fmt_buf() - if fb4 is not None: - viperlib.snprintf(fb4, 1024, "入口文件: %s", src_path) - log.info(fb4, "project") + viperlib.snprintf(fmtbuf, 1024, "入口文件: %s", src_path) + log.info(fmtbuf, "project") + if src_path is not None: - if log is not None: - log.banner("AST 解析") + log.banner("AST 解析") # 打开文件 f: fileio.File | t.CPtr = fileio.File(src_path, fileio.MODE.R) if f.closed: - if log is not None: - fb5: str = VLogger.fmt_buf() - if fb5 is not None: - viperlib.snprintf(fb5, 1024, "无法打开文件: %s", src_path) - log.error(fb5, "fileio") + viperlib.snprintf(fmtbuf, 1024, "无法打开文件: %s", src_path) + log.error(fmtbuf, "fileio") argparse.release(args) return 1 # 分配源代码缓冲区 src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE) if src_buf is None: - if log is not None: - log.error("malloc for src_buf failed", "memhub") + log.error("malloc for src_buf failed", "memhub") f.close() argparse.release(args) return 1 @@ -471,11 +431,8 @@ Target: %s bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE) f.close() if bytes_read < 0: - if log is not None: - fb6: str = VLogger.fmt_buf() - if fb6 is not None: - viperlib.snprintf(fb6, 1024, "读取文件失败 (错误码: %d)", bytes_read) - log.error(fb6, "fileio") + viperlib.snprintf(fmtbuf, 1024, "读取文件失败 (错误码: %d)", bytes_read) + log.error(fmtbuf, "fileio") argparse.release(args) return 1 # 添加 null 终止符,确保 strlen 和 SHA1 计算正确 @@ -483,12 +440,9 @@ Target: %s src_buf[bytes_read] = 0 else: src_buf[SRC_BUF_SIZE - 1] = 0 - if log is not None: log.info("文件读取完成", "fileio") - fb7: str = VLogger.fmt_buf() - if fb7 is not None: - viperlib.snprintf(fb7, 1024, "读取 %d 字节", bytes_read) - log.info(fb7, "fileio") + viperlib.snprintf(fmtbuf, 1024, "读取 %d 字节", bytes_read) + log.info(fmtbuf, "fileio") # 解析 AST(拆分为词法+语法两阶段,便于调试) ast._init_tables(mb) lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) @@ -496,14 +450,12 @@ Target: %s tokens: ast.Token | t.CPtr = ast.tokenize(lx) tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) if tree is None: - if log is not None: - log.error("AST 解析失败", "ast") + log.error("AST 解析失败", "ast") argparse.release(args) return 1 # === 翻译 AST → LLVM IR === - if log is not None: - log.banner("LLVM IR 翻译") + log.banner("LLVM IR 翻译") tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() result: int = tr.translate(tree) if result == 0: @@ -513,8 +465,7 @@ Target: %s tr.dump_ir(ir_buf, IR_BUF_SIZE, llvmlite.OUTPUT_FULL) # === 编译管线: .ll → .obj → .exe === - if log is not None: - log.banner("编译管线") + log.banner("编译管线") # module_name 用源代码内容的 SHA1(前 16 字符),与 Projectrans.py 一致 # output_name 从文件名推导(如 test.vp -> test.exe),保持可读性 @@ -582,8 +533,7 @@ Target: %s # === Phase1 stub 分离:使用 OUTPUT_STUB/TEXT 模式分别生成 stub.ll 和 text.ll === if do_phase1 != 0 and temp_dir is not None and module_name is not None: - if log is not None: - log.banner("stub 分离") + log.banner("stub 分离") SF_IR_SIZE: t.CSizeT = 262144 td_len_sf: t.CSizeT = string.strlen(temp_dir) # 保存 stub.ll @@ -615,8 +565,7 @@ Target: %s # phase=1 模式:仅生成 stub,不执行编译 if do_phase2 == 0: - if log is not None: - log.success("Phase1 完成(仅 stub 分离,跳过编译)") + log.success("Phase1 完成(仅 stub 分离,跳过编译)") argparse.release(args) return 0 @@ -624,8 +573,7 @@ Target: %s final_ir: bytes = ir_buf final_ir_len: t.CSizeT = ir_len if temp_dir is not None and module_name is not None: - if log is not None: - log.banner("IR 组合") + log.banner("IR 组合") SF_COMBINED_SIZE: t.CSizeT = 4194304 # 4MB combined_buf: bytes = stdlib.malloc(SF_COMBINED_SIZE) if combined_buf is not None: @@ -643,47 +591,32 @@ Target: %s includes_binary_dir ) if br is not None and br.Success == 1: - if log is not None: - log.success("编译管线完成") - fb8: str = VLogger.fmt_buf() - if fb8 is not None: - viperlib.snprintf(fb8, 1024, "输出: %s/%s", output_dir, linker_output) - log.info(fb8) + log.success("编译管线完成") + viperlib.snprintf(fmtbuf, 1024, "输出: %s/%s", output_dir, linker_output) + log.info(fmtbuf) # --run 模式:执行生成的可执行文件 # phase2command 模式:exe 尚未链接(命令在 bat 中),跳过 --run if args.get_bool("run") and BuildPipeline._phase2_cmd_path is None: exe_path: bytes = stdlib.malloc(string.strlen(output_dir) + string.strlen(linker_output) + 2) if exe_path is not None: viperlib.snprintf(exe_path, 256, "%s/%s", output_dir, linker_output) - if log is not None: - fb9: str = VLogger.fmt_buf() - if fb9 is not None: - viperlib.snprintf(fb9, 1024, "执行: %s", exe_path) - log.info(fb9, "run") + viperlib.snprintf(fmtbuf, 1024, "执行: %s", exe_path) + log.info(fmtbuf) r: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False) if r is not None: - if log is not None: - fb10: str = VLogger.fmt_buf() - if fb10 is not None: - viperlib.snprintf(fb10, 1024, "退出码: %d", r.returncode) - log.info(fb10, "run") + viperlib.snprintf(fmtbuf, 1024, "退出码: %d", r.returncode) + log.info(fmtbuf) else: - if log is not None: - log.error("编译管线失败", "pipeline") - if br is not None and br.ErrorMsg is not None: - fb11: str = VLogger.fmt_buf() - if fb11 is not None: - viperlib.snprintf(fb11, 1024, "编译管线失败: %s", br.ErrorMsg) - log.error(fb11, "FATAL") + log.error("编译管线失败", "pipeline") + if br is not None and br.ErrorMsg is not None: + viperlib.snprintf(fmtbuf, 1024, "编译管线失败: %s", br.ErrorMsg) + log.error(fmtbuf, "FATAL") sys.exit(1) else: - if log is not None: - log.error("malloc for IR buffer failed", "memhub") + log.error("malloc for IR buffer failed", "memhub") else: - if log is not None: - log.error("翻译失败", "translator") + log.error("翻译失败", "translator") argparse.release(args) - if log is not None: - log.success("TransPyV 完成") + log.success("TransPyV 完成") return 0