fix(TPV): 统一浮点 CDefine 注册路径 + 1a 预扫描签名防 UAF - handle_module_level_var/PreScan 统一走 _register_cdefine_from_value(浮点/整数自动识别); 新增 register_cdefine_double/lookup_cdefine_double(%.17g 存值); translate_name_value 浮点 CDefine 返回 ConstFloat(修复 llc ret i32 0); 1a 预扫描函数签名提前泛型特化到 mark1 前(防 UAF); 移除 ASSIGN-DBG; 临时定位插桩 CDEF-DBG
This commit is contained in:
1 parent
aa6eee54e9
commit
24d3de4b72
5 files changed
+177
-28
No files matched your search
@@ -122,6 +122,33 @@ def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _register_cdefine_from_value - 注册 CDefine 常量(浮点/整数自动识别)
|
||||
#
|
||||
# 浮点字面量(如 vipermath 的 U_M_PI: t.CDefine = 3.14159...)走
|
||||
# register_cdefine_double,否则 translate_value 查表得 0 生成
|
||||
# ret i32 0(llc 报错 "value doesn't match function result type")。
|
||||
# ============================================================
|
||||
def _register_cdefine_from_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, val_node: ast.AST | t.CPtr) -> None:
|
||||
"""注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数)"""
|
||||
if pool is None or name is None:
|
||||
return
|
||||
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:
|
||||
# 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))
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
HandlesType.register_cdefine_double(pool, name, cn_fp.float_val)
|
||||
return
|
||||
val_fp: int = extract_cdefine_int_value(val_node)
|
||||
HandlesType.register_cdefine_constant(pool, name, val_fp)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _annotation_contains_name - 递归检查注解中是否包含指定名称
|
||||
#
|
||||
@@ -284,10 +311,10 @@ class AnnAssignHandle(HandlesBase.Mixin):
|
||||
|
||||
# CDefine 注解: 不创建 alloca,但注册常量到全局表
|
||||
# 供后续 t.CArray[elem_ty, NAME] 编译期解析使用
|
||||
# 浮点/整数自动识别(与 Handle/handle_module_level_var 路径一致)
|
||||
if is_cdefine_annotation(aa.annotation) != 0:
|
||||
pool_ps: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
val_ps: int = extract_cdefine_int_value(aa.value)
|
||||
HandlesType.register_cdefine_constant(pool_ps, nm.id, val_ps)
|
||||
_register_cdefine_from_value(pool_ps, nm.id, aa.value)
|
||||
return 0
|
||||
|
||||
# global/nonlocal 变量不需要局部 alloca
|
||||
@@ -394,8 +421,7 @@ class AnnAssignHandle(HandlesBase.Mixin):
|
||||
# 注: PreScan 已注册过,此处保证即使跳过 PreScan 也能正确注册
|
||||
if is_cdefine_annotation(aa.annotation) != 0:
|
||||
pool_cd: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
val_cd: int = extract_cdefine_int_value(aa.value)
|
||||
HandlesType.register_cdefine_constant(pool_cd, nm.id, val_cd)
|
||||
_register_cdefine_from_value(pool_cd, nm.id, aa.value)
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
|
||||
@@ -2279,10 +2279,6 @@ def _specialize_generic_class(trans: HT.Translator | t.CPtr,
|
||||
type_args.set(ta_i_g, ta_rsv_g)
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
fb_spc: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_spc is not None:
|
||||
viperlib.snprintf(fb_spc, 1024, "_specialize_generic_class: %s declare_only=%d", class_name, trans._declare_only)
|
||||
VLogger.info(fb_spc, "TC-DBG")
|
||||
|
||||
# ============================================================
|
||||
# 诊断输出:追踪 GSListNode 特化调用路径
|
||||
@@ -2470,10 +2466,6 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
class_name: str = cd.name
|
||||
fb_tcd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_tcd is not None:
|
||||
viperlib.snprintf(fb_tcd, 1024, "translate_class_def: %s line=%d", class_name, cd.lineno)
|
||||
VLogger.info(fb_tcd, "TC-DBG")
|
||||
|
||||
# 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前,
|
||||
# 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类)
|
||||
@@ -3500,10 +3492,6 @@ def _translate_method(trans: HT.Translator | t.CPtr,
|
||||
"""翻译单个方法,返回 0"""
|
||||
if trans is None or fd is None or struct_ty is None or class_name is None:
|
||||
return 0
|
||||
fb_tm: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_tm is not None:
|
||||
viperlib.snprintf(fb_tm, 1024, "_translate_method: %s.%s", class_name, fd.name)
|
||||
VLogger.info(fb_tm, "TC-DBG")
|
||||
|
||||
# 懒导入
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
|
||||
@@ -1876,11 +1876,26 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if nm_id is None:
|
||||
return None
|
||||
|
||||
# CDefine 编译期常量: 直接返回整数常量值(不生成运行时代码)
|
||||
# CDefine 编译期常量: 返回常量值(浮点 CDefine → double 常量,整数 → i32)
|
||||
# NAME: t.CDefine = value 形式定义的常量在编译期已注册到本地表
|
||||
cdef_val: int = HandlesType.lookup_cdefine_constant(nm_id)
|
||||
# 浮点 CDefine(如 vipermath 的 U_M_PI=3.14...)必须返回浮点常量,
|
||||
# 否则在 double 函数里 return 生成 ret i32 0(llc 报错)。
|
||||
cdef_val_d: double = HandlesType.lookup_cdefine_double(nm_id)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return llvmlite.const_int32(pool, cdef_val)
|
||||
if HandlesType.is_cdefine_double() != 0:
|
||||
# CDEF-DBG: 打印浮点 CDefine 使用(返回 ConstFloat)
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
viperlib.snprintf(fb_cd, 1024, "USE-D: %s -> %.17g (float)", nm_id, cdef_val_d)
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
return llvmlite.ConstFloat(pool, llvmlite.Double(pool), cdef_val_d)
|
||||
cdef_val_i: int = t.CInt(cdef_val_d)
|
||||
# CDEF-DBG: 打印整数 CDefine 使用(返回 const_int32)
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
viperlib.snprintf(fb_cd, 1024, "USE-I: %s -> %d (int)", nm_id, cdef_val_i)
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
return llvmlite.const_int32(pool, cdef_val_i)
|
||||
|
||||
# 本地表未找到:尝试跨模块 .vpi 查找(保证多模块查表存表一致)
|
||||
# 仅对符合 CDefine 命名约定(ALL_CAPS)的名字触发跨模块查找,
|
||||
|
||||
@@ -87,10 +87,6 @@ def translate_children(trans: HT.Translator | t.CPtr,
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None: continue
|
||||
kd: int = child.kind()
|
||||
fb_tc: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_tc is not None:
|
||||
viperlib.snprintf(fb_tc, 1024, "translate_children[%d]: kind=%d line=%d", ci, kd, child.lineno)
|
||||
VLogger.info(fb_tc, "TC-DBG")
|
||||
|
||||
# _declare_only == 0 时,_translate_module_level 已预处理导入语句,
|
||||
# 此处跳过避免重复处理(from_imports 条目重复)
|
||||
@@ -109,6 +105,13 @@ def translate_children(trans: HT.Translator | t.CPtr,
|
||||
added_total += added
|
||||
elif trans._declare_only == 1:
|
||||
_register_cexport_from_funcdef(trans, child)
|
||||
# 预解析函数签名类型,触发泛型类特化(如 numpy 的 _empty_like
|
||||
# 签名 ndarray[t.CDouble] → 特化结构体注册)。
|
||||
# 1a 阶段在 mark1 之前,特化结构体的 Ty/Fields 分配在 mark1 前,
|
||||
# 不被 1b 的 mark/reset 回收 → 避免 Phase2 翻译 App 文件时 UAF
|
||||
# (Phase1 1b 才触发特化时,结构体 Ty/Fields 在 pool 被 reset 覆写)。
|
||||
# 仅触发特化,不验证结果(1b 全量翻译时仍会重新解析)。
|
||||
_prescan_funcdef_signatures(trans, child)
|
||||
elif kd == ast.ASTKind.ClassDef:
|
||||
# ClassDef 在模块级直接处理(不需要 builder)
|
||||
# _declare_only=2(import扫描模式)时跳过,只处理 import 依赖
|
||||
@@ -133,6 +136,38 @@ def translate_children(trans: HT.Translator | t.CPtr,
|
||||
return added_total
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _prescan_funcdef_signatures - 1a 阶段预解析模块级函数签名
|
||||
#
|
||||
# 触发泛型类特化(如 numpy 的 _empty_like 签名 ndarray[t.CDouble]),
|
||||
# 使特化结构体在 mark1 前注册(Ty/Fields 不被 1b 的 mark/reset 回收),
|
||||
# 避免 Phase2 翻译 App 文件时访问悬空结构体(UAF)。
|
||||
# 仅解析类型触发特化,不验证结果(1b 全量翻译时重新解析)。
|
||||
# ============================================================
|
||||
def _prescan_funcdef_signatures(trans: HT.Translator | t.CPtr,
|
||||
fd: ast.FunctionDef | t.CPtr) -> None:
|
||||
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化"""
|
||||
if trans is None or fd is None:
|
||||
return
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is None:
|
||||
return
|
||||
imp: str = trans._imported_modules
|
||||
fi: str = trans._from_imports
|
||||
if fd.returns is not None:
|
||||
HandlesType.resolve_annotation_type(pool, fd.returns, imp, fi, trans)
|
||||
if fd.args is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args)
|
||||
if ags.args is not None:
|
||||
al: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = al.__len__()
|
||||
ai: t.CSizeT
|
||||
for ai in range(an):
|
||||
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(al.get(ai))
|
||||
if ag is not None and ag.annotation is not None:
|
||||
HandlesType.resolve_annotation_type(pool, ag.annotation, imp, fi, trans)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器
|
||||
#
|
||||
@@ -280,8 +315,9 @@ def handle_module_level_var(trans: HT.Translator | t.CPtr,
|
||||
nm_cd: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa_cd.target)
|
||||
if nm_cd.id is not None:
|
||||
if HandlesAnnAssign.is_cdefine_annotation(aa_cd.annotation) != 0:
|
||||
val_cd: int = HandlesAnnAssign.extract_cdefine_int_value(aa_cd.value)
|
||||
HandlesType.register_cdefine_constant(pool, nm_cd.id, val_cd)
|
||||
# 浮点/整数自动识别注册(浮点 CDefine 如 vipermath U_M_PI)
|
||||
HandlesAnnAssign._register_cdefine_from_value(
|
||||
pool, nm_cd.id, aa_cd.value)
|
||||
return 0
|
||||
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine,不创建全局变量
|
||||
|
||||
@@ -156,6 +156,10 @@ _g_generic_type_args: list[str] | t.CPtr = None
|
||||
# ============================================================
|
||||
_g_cdefine_names: list[str] | t.CPtr = None
|
||||
_g_cdefine_values: list[str] | t.CPtr = None
|
||||
# 浮点 CDefine 标志(1=浮点常量,值存 %f 文本;0=整数常量)
|
||||
_g_cdefine_double_flags: list[int] | t.CPtr = None
|
||||
# 最近一次 lookup 是否浮点 CDefine(与 _g_cdefine_found 配合)
|
||||
_g_cdefine_is_double: int = 0
|
||||
|
||||
# ============================================================
|
||||
# 当前模块 SHA1(Phase1 在模块开始翻译前设置,供报错使用)
|
||||
@@ -176,10 +180,11 @@ def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
|
||||
值以十进制字符串存储。注意:value 是 32 位有符号整数,
|
||||
0xFFFFFFFF 会存储为 "-1",lookup 时用 found 标志区分"未找到"和值为 -1。
|
||||
"""
|
||||
global _g_cdefine_names, _g_cdefine_values
|
||||
global _g_cdefine_names, _g_cdefine_values, _g_cdefine_double_flags
|
||||
if _g_cdefine_names is None:
|
||||
_g_cdefine_names = list[str](pool, 64)
|
||||
_g_cdefine_values = list[str](pool, 64)
|
||||
_g_cdefine_double_flags = list[int](pool, 64)
|
||||
_g_cdefine_names.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
@@ -187,6 +192,36 @@ def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
|
||||
_g_cdefine_values.append(val_buf)
|
||||
else:
|
||||
_g_cdefine_values.append("0")
|
||||
if _g_cdefine_double_flags is not None:
|
||||
_g_cdefine_double_flags.append(0)
|
||||
|
||||
|
||||
def register_cdefine_double(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: double) -> None:
|
||||
"""注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...)
|
||||
|
||||
值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。
|
||||
"""
|
||||
global _g_cdefine_names, _g_cdefine_values, _g_cdefine_double_flags
|
||||
if _g_cdefine_names is None:
|
||||
_g_cdefine_names = list[str](pool, 64)
|
||||
_g_cdefine_values = list[str](pool, 64)
|
||||
_g_cdefine_double_flags = list[int](pool, 64)
|
||||
_g_cdefine_names.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
viperlib.snprintf(val_buf, 32, "%.17g", value)
|
||||
_g_cdefine_values.append(val_buf)
|
||||
else:
|
||||
_g_cdefine_values.append("0")
|
||||
if _g_cdefine_double_flags is not None:
|
||||
_g_cdefine_double_flags.append(1)
|
||||
# CDEF-DBG: 打印注册的浮点 CDefine(定位 llc ret i32 0)
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
viperlib.snprintf(fb_cd, 1024, "REG-D: %s = %.17g (buf=%s)",
|
||||
name, value, val_buf if val_buf is not None else "(null)")
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
|
||||
|
||||
def lookup_cdefine_constant(name: str) -> int:
|
||||
@@ -195,9 +230,11 @@ def lookup_cdefine_constant(name: str) -> int:
|
||||
返回找到的值。由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1),
|
||||
用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。
|
||||
调用方应在调用后检查 _g_cdefine_found。
|
||||
浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。
|
||||
"""
|
||||
global _g_cdefine_found
|
||||
global _g_cdefine_found, _g_cdefine_is_double
|
||||
_g_cdefine_found = 0
|
||||
_g_cdefine_is_double = 0
|
||||
if _g_cdefine_names is None:
|
||||
return 0
|
||||
n: t.CSizeT = _g_cdefine_names.__len__()
|
||||
@@ -208,10 +245,56 @@ def lookup_cdefine_constant(name: str) -> int:
|
||||
val_str: str = _g_cdefine_values.get(i)
|
||||
if val_str is not None:
|
||||
_g_cdefine_found = 1
|
||||
if _g_cdefine_double_flags is not None and _g_cdefine_double_flags.get(i) == 1:
|
||||
_g_cdefine_is_double = 1
|
||||
return string.atoi(val_str)
|
||||
return string.atoi(val_str)
|
||||
return 0
|
||||
|
||||
|
||||
def lookup_cdefine_double(name: str) -> double:
|
||||
"""查找 CDefine 编译期常量,返回 double 值(浮点/整数统一)
|
||||
|
||||
与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double
|
||||
(found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。
|
||||
"""
|
||||
global _g_cdefine_found, _g_cdefine_is_double
|
||||
_g_cdefine_found = 0
|
||||
_g_cdefine_is_double = 0
|
||||
if _g_cdefine_names is None:
|
||||
return 0.0
|
||||
n: t.CSizeT = _g_cdefine_names.__len__()
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = _g_cdefine_names.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = _g_cdefine_values.get(i)
|
||||
if val_str is not None:
|
||||
_g_cdefine_found = 1
|
||||
if _g_cdefine_double_flags is not None and _g_cdefine_double_flags.get(i) == 1:
|
||||
_g_cdefine_is_double = 1
|
||||
ret_d: double = string.atof(val_str)
|
||||
# CDEF-DBG: 打印浮点查找命中
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
viperlib.snprintf(fb_cd, 1024, "LOOKUP-D: %s -> buf=%s atof=%.17g", name, val_str, ret_d)
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
return ret_d
|
||||
ret_i2: double = double(string.atoi(val_str))
|
||||
# CDEF-DBG: 打印整数查找命中
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
viperlib.snprintf(fb_cd, 1024, "LOOKUP-I: %s -> buf=%s atoi=%d", name, val_str, string.atoi(val_str))
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
return ret_i2
|
||||
return 0.0
|
||||
|
||||
|
||||
def is_cdefine_double() -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是浮点常量"""
|
||||
return _g_cdefine_is_double
|
||||
|
||||
|
||||
_g_cdefine_found: int = 0
|
||||
|
||||
|
||||
@@ -228,9 +311,10 @@ def set_cdefine_found(val: int) -> None:
|
||||
|
||||
def clear_cdefine_constants() -> None:
|
||||
"""清空 CDefine 常量表(模块切换时调用)"""
|
||||
global _g_cdefine_names, _g_cdefine_values
|
||||
global _g_cdefine_names, _g_cdefine_values, _g_cdefine_double_flags
|
||||
_g_cdefine_names = None
|
||||
_g_cdefine_values = None
|
||||
_g_cdefine_double_flags = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
Reference in new issue
Block a user