diff --git a/App/lib/core/Handles/HandlesAnnAssign.vp b/App/lib/core/Handles/HandlesAnnAssign.vp index 5356d3a..cd37b36 100644 --- a/App/lib/core/Handles/HandlesAnnAssign.vp +++ b/App/lib/core/Handles/HandlesAnnAssign.vp @@ -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 diff --git a/App/lib/core/Handles/HandlesClassDef.vp b/App/lib/core/Handles/HandlesClassDef.vp index 4434887..5875939 100644 --- a/App/lib/core/Handles/HandlesClassDef.vp +++ b/App/lib/core/Handles/HandlesClassDef.vp @@ -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 diff --git a/App/lib/core/Handles/HandlesExpr.vp b/App/lib/core/Handles/HandlesExpr.vp index 5d9ee28..2a93826 100644 --- a/App/lib/core/Handles/HandlesExpr.vp +++ b/App/lib/core/Handles/HandlesExpr.vp @@ -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)的名字触发跨模块查找, diff --git a/App/lib/core/Handles/HandlesMain.vp b/App/lib/core/Handles/HandlesMain.vp index ffc188c..f5b0893 100644 --- a/App/lib/core/Handles/HandlesMain.vp +++ b/App/lib/core/Handles/HandlesMain.vp @@ -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,不创建全局变量 diff --git a/App/lib/core/Handles/HandlesType.vp b/App/lib/core/Handles/HandlesType.vp index e79e2c5..857f1bd 100644 --- a/App/lib/core/Handles/HandlesType.vp +++ b/App/lib/core/Handles/HandlesType.vp @@ -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 # ============================================================