fix(TPV): 浮点 CDefine 注册多方案绕开 pool 覆写与跨模块 double 传递问题 - 查表/str_val/源文件重读+atof_out 输出参数; PRE-TR/PRE-ML/REG-SRC 定位插桩; 记录浮点节点构造值表

This commit is contained in:
TermiNexus committed 2026-08-08 19:42:54 +08:00
1 parent 24d3de4b72
commit 92ba3af752
4 files changed
+174 -3

No files matched your search

+129 -3
View File
@@ -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 - 递归检查注解中是否包含指定名称
#