From 92ba3af752df1afc20d54c40d28cf0a931305b1c Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 8 Aug 2026 19:42:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(TPV):=20=E6=B5=AE=E7=82=B9=20CDefine=20?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E5=A4=9A=E6=96=B9=E6=A1=88=E7=BB=95=E5=BC=80?= =?UTF-8?q?=20pool=20=E8=A6=86=E5=86=99=E4=B8=8E=E8=B7=A8=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=20double=20=E4=BC=A0=E9=80=92=E9=97=AE=E9=A2=98=20-?= =?UTF-8?q?=20=E6=9F=A5=E8=A1=A8/str=5Fval/=E6=BA=90=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=87=8D=E8=AF=BB+atof=5Fout=20=E8=BE=93=E5=87=BA=E5=8F=82?= =?UTF-8?q?=E6=95=B0;=20PRE-TR/PRE-ML/REG-SRC=20=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=E6=8F=92=E6=A1=A9;=20=E8=AE=B0=E5=BD=95=E6=B5=AE=E7=82=B9?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E6=9E=84=E9=80=A0=E5=80=BC=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/BuildPipeline.vp | 2 + App/lib/core/Handles/HandlesAnnAssign.vp | 132 +++++++++++++++++++++- App/lib/core/Handles/HandlesTranslator.vp | 2 + App/lib/core/Handles/HandlesType.vp | 41 +++++++ 4 files changed, 174 insertions(+), 3 deletions(-) diff --git a/App/lib/core/BuildPipeline.vp b/App/lib/core/BuildPipeline.vp index a91876d..534dae5 100644 --- a/App/lib/core/BuildPipeline.vp +++ b/App/lib/core/BuildPipeline.vp @@ -132,6 +132,8 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, if string.strstr(file_path, "includes") is not None: strict_mode = 0 HandlesStruct.reset_visible_structs(mb, strict_mode) + # CHK-FLOAT: translate 前检查浮点 Constant(二分定位覆写阶段) + HandlesType._dbg_check_ast_floats(mb, tree, "PRE-TR") ret: int = tr.translate(tree) if ret != 0: return None diff --git a/App/lib/core/Handles/HandlesAnnAssign.vp b/App/lib/core/Handles/HandlesAnnAssign.vp index cd37b36..518fc53 100644 --- a/App/lib/core/Handles/HandlesAnnAssign.vp +++ b/App/lib/core/Handles/HandlesAnnAssign.vp @@ -5,6 +5,8 @@ import llvmlite import memhub import string import stdio +import stdlib +import w32.fileio as fileio import lib.core.Handles.HandlesBase as HandlesBase import lib.core.Handles.HandlesTranslator as HT import lib.core.Handles.HandlesVar as HandlesVar @@ -137,18 +139,142 @@ def _register_cdefine_from_value(pool: memhub.MemBuddy | t.CPtr, if val_node is not None and val_node.kind() == ast.ASTKind.Constant: cn_fp: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node) if cn_fp.const_kind == ast.CONST_FLOAT: + # 源文件重读恢复(最可靠:AST 节点 float_val 可能被 pool 操作覆写, + # 源文件文本不受影响;用输出参数绕开跨模块 double 返回值传递 bug) + use_val: double = cn_fp.float_val + rec_d: t.CDouble = 0.0 + if _recover_cdefine_float(name, t.CPtr(c.Addr(rec_d))) != 0: + use_val = rec_d # CDEF-DBG: 打印 float_val 读取(定位浮点 CDefine 值错误) fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() if fb_cd is not None: - viperlib.snprintf(fb_cd, 1024, "REG-SRC: %s kind=%d const_kind=%d int_val=%lld float_val=%.17g ptr=%p", - name, val_node.kind(), cn_fp.const_kind, cn_fp.int_val, cn_fp.float_val, t.CSizeT(cn_fp)) + viperlib.snprintf(fb_cd, 1024, "REG-SRC: %s kind=%d const_kind=%d float_val=%.17g rec=%.17g use=%.17g ptr=%p", + name, val_node.kind(), cn_fp.const_kind, cn_fp.float_val, + rec_d, use_val, t.CSizeT(cn_fp)) VLogger.info(fb_cd, "CDEF-DBG") - HandlesType.register_cdefine_double(pool, name, cn_fp.float_val) + HandlesType.register_cdefine_double(pool, name, use_val) return val_fp: int = extract_cdefine_int_value(val_node) HandlesType.register_cdefine_constant(pool, name, val_fp) +# ============================================================ +# 源文件重读恢复 CDefine 浮点值 +# +# 背景:AST 节点的 float_val/str_val 字段可能被 pool 分配操作覆写 +# (MemBuddy 内存冲突),导致注册的浮点 CDefine 值错误(llc ret i32 0)。 +# 本函数直接读源文件找 "NAME: t.CDefine = value" 行,atof 解析 value—— +# 源文件文本不受 pool 影响,是最可靠的恢复路径。 +# ============================================================ +_g_recover_found: int = 0 + + +def _recover_found() -> int: + """检查最近一次 _recover_cdefine_float 是否成功""" + return _g_recover_found + + +def _recover_cdefine_float(name: str, out: t.CDouble | t.CPtr) -> int: + """从当前模块源文件恢复浮点 CDefine 值,写入 out[0],成功返回 1 + + 用输出参数传递 double,避免 TPV 跨模块 double 返回值传递 bug。 + """ + global _g_recover_found + _g_recover_found = 0 + fp: str = HandlesType.get_current_file() + if fp is None or name is None or out is None: + return 0 + f: fileio.File | t.CPtr = fileio.File(fp, fileio.MODE.R) + if f.closed: + return 0 + BUF_SZ: t.CSizeT = 1048576 + buf: bytes = stdlib.malloc(BUF_SZ) + if buf is None: + f.close() + return 0 + nrd: LONG = f.read_all(buf, BUF_SZ) + f.close() + if nrd <= 0: + stdlib.free(buf) + return 0 + if nrd < BUF_SZ: + buf[nrd] = 0 + else: + buf[BUF_SZ - 1] = 0 + + name_len: t.CSizeT = string.strlen(name) + total_len: t.CSizeT = string.strlen(buf) + pos: t.CSizeT = 0 + while pos < total_len: + line_start: t.CSizeT = pos + while pos < total_len and buf[pos] != '\n': + pos += 1 + line_len: t.CSizeT = pos - line_start + if pos < total_len: + pos += 1 + + # 匹配 "name:" + if line_len < name_len + 1: + continue + match_ok: int = 1 + ki: t.CSizeT + for ki in range(name_len): + if buf[line_start + ki] != name[ki]: + match_ok = 0 + break + if match_ok == 0: + continue + if buf[line_start + name_len] != ':': + continue + + # 行内包含 "t.CDefine" + has_cd: int = 0 + ci: t.CSizeT = line_start + name_len + 1 + while ci + 8 <= line_start + line_len: + if (buf[ci] == 't' and buf[ci + 1] == '.' and buf[ci + 2] == 'C' and + buf[ci + 3] == 'D' and buf[ci + 4] == 'e' and buf[ci + 5] == 'f' and + buf[ci + 6] == 'i' and buf[ci + 7] == 'n' and buf[ci + 8] == 'e'): + has_cd = 1 + break + ci += 1 + if has_cd == 0: + continue + + # 找 '=' + eq: t.CSizeT = line_start + while eq < line_start + line_len and buf[eq] != '=': + eq += 1 + if eq >= line_start + line_len: + continue + eq += 1 + while eq < line_start + line_len and buf[eq] == ' ': + eq += 1 + val_start: t.CSizeT = eq + while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' \ + and buf[eq] != '#' and buf[eq] != '\r' and buf[eq] != '\n': + eq += 1 + if eq == val_start: + continue + + val_txt: str = stdlib.malloc(eq - val_start + 1) + if val_txt is None: + stdlib.free(buf) + return 0 + vi: t.CSizeT + for vi in range(eq - val_start): + val_txt[vi] = buf[val_start + vi] + val_txt[eq - val_start] = 0 + stdlib.free(buf) + # 用 atof_out(输出参数)绕开跨模块 double 返回值传递 bug + if string.atof_out(val_txt, out) != 0: + _g_recover_found = 1 + return 1 + return 0 + + stdlib.free(buf) + return 0 + + # ============================================================ # _annotation_contains_name - 递归检查注解中是否包含指定名称 # diff --git a/App/lib/core/Handles/HandlesTranslator.vp b/App/lib/core/Handles/HandlesTranslator.vp index 8ae01e8..4c8be3f 100644 --- a/App/lib/core/Handles/HandlesTranslator.vp +++ b/App/lib/core/Handles/HandlesTranslator.vp @@ -296,6 +296,8 @@ class Translator: break if self._declare_only != 0: + # CHK-FLOAT: 模块级翻译前检查(二分定位覆写阶段) + HandlesType._dbg_check_ast_floats(pool, tree, "PRE-ML") # Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder self._translate_module_level(pool, mod, tree) elif has_user_main == 0: diff --git a/App/lib/core/Handles/HandlesType.vp b/App/lib/core/Handles/HandlesType.vp index 857f1bd..b610188 100644 --- a/App/lib/core/Handles/HandlesType.vp +++ b/App/lib/core/Handles/HandlesType.vp @@ -173,6 +173,47 @@ def set_current_module_sha1(sha1: str) -> None: _g_current_module_sha1 = sha1 +# ============================================================ +# _dbg_check_ast_floats - CHK-FLOAT 二分插桩(定位浮点 CDefine 值错误) +# +# 遍历 AST 树,打印所有 CONST_FLOAT 节点的 float_val。 +# 在多个时间点调用(PRE-TR=translate 前 / PRE-ML=模块级翻译前), +# 二分定位 Constant 节点 float_val 被覆写的具体阶段。 +# ============================================================ +def _dbg_check_ast_floats(mb: memhub.MemBuddy | t.CPtr, + tree: ast.AST | t.CPtr, tag: str): + """CHK-FLOAT: 遍历 AST 检查所有浮点 Constant 节点""" + if tree is None: + return + if tree.kind() == ast.ASTKind.Constant: + cn_f: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(tree) + if cn_f.const_kind == ast.CONST_FLOAT: + fb_chk: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_chk is not None: + viperlib.snprintf(fb_chk, 1024, "[CHK-FLOAT] %s ptr=%p float_val=%.17g", + tag, t.CSizeT(cn_f), cn_f.float_val) + VLogger.info(fb_chk, "CHK") + return + # AnnAssign: value/annotation/target 不在 children 里,单独遍历 + if tree.kind() == ast.ASTKind.AnnAssign: + aa_f: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(tree) + if aa_f.value is not None: + _dbg_check_ast_floats(mb, aa_f.value, tag) + if aa_f.annotation is not None: + _dbg_check_ast_floats(mb, aa_f.annotation, tag) + if aa_f.target is not None: + _dbg_check_ast_floats(mb, aa_f.target, tag) + return + ch_f: list[ast.AST | t.CPtr] | t.CPtr = tree.children + if ch_f is not None: + n_f: t.CSizeT = ch_f.__len__() + i_f: t.CSizeT + for i_f in range(n_f): + c_f: ast.AST | t.CPtr = ch_f.get(i_f) + if c_f is not None: + _dbg_check_ast_floats(mb, c_f, tag) + + def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr, name: str, value: int) -> None: """注册 CDefine 编译期常量到本地表