fix(llvmlite): PrintModule param_scan 改用访问器绕开 stub 字段访问陷阱

printf.fmt Param 创建后 next=0(正常)、dump_ir 诊断访问器读 next=0,
但 PrintModule 直接访问 param_scan.Next 遍历超限死循环——同一指针两次
读取结果不同,指向跨模块 stub 字段访问生成错误 GEP/静默跳过
(param_scan 永不更新 → 死循环)。param_scan 遍历改用 param_get_next/
param_get_ty(__function.vp 完整类型内读取),并打印首节点 param/next
供对比验证。
This commit is contained in:
TermiNexus committed 2026-08-18 08:26:38 +08:00
1 parent 37e6dd1863
commit 4f95867209
1 file changed
+16 -6
+16 -6
View File
@@ -7,7 +7,7 @@ import viperlib
import memhub
from linkedlist import GSList, GSListNode
from .__types import LLVMType, TypePrint, Array, PrintStructDefinition, get_struct_name, Struct, ParamNode
from .__function import Function, FunctionPrint, _ll_name_needs_quote, Param
from .__function import Function, FunctionPrint, _ll_name_needs_quote, Param, param_get_next, param_get_ty
# ============================================================
@@ -239,15 +239,25 @@ class LLVMModule:
if func_scan.Params is not None:
param_scan: Param | t.CPtr = func_scan.Params.Head
param_scan_steps: t.CSizeT = 0
if param_scan is not None:
# 诊断(builtins.vp dump 卡死根因排查):对比访问器与
# 直接字段访问的 param0/next——stub 字段访问若生成错误
# GEP 会读到垃圾导致死循环。
stdio.printf("[DIAG] param_scan 首节点: param=%llu next=%llu(函数名=%s)\n",
t.CUInt64T(param_scan), t.CUInt64T(param_scan.Next), func_scan.Name)
while param_scan is not None:
param_scan_steps += 1
if param_scan_steps > IR_DUMP_CHAIN_LIMIT:
stdio.printf("[IR-DUMP] 链表异常: func params(函数名=%s,Params.Count=%zu,遍历超 %d 步,终止)\n",
func_scan.Name, func_scan.Params.Count, IR_DUMP_CHAIN_LIMIT)
stdio.printf("[IR-DUMP] 链表异常: func params(函数名=%s,Params.Count=%zu,param=%llu next=%llu,遍历超 %d 步,终止)\n",
func_scan.Name, func_scan.Params.Count,
t.CUInt64T(param_scan), t.CUInt64T(param_scan.Next), IR_DUMP_CHAIN_LIMIT)
stdlib.exit(1)
if param_scan.Ty is not None:
self.ensure_opaque_for_type(pool, param_scan.Ty)
param_scan = param_scan.Next
# 用访问器(__function.vp 完整类型内)绕开 stub 字段访问
# 陷阱:跨模块 struct 字段访问可能生成错误 GEP/静默跳过,
# 导致 param_scan 永不更新死循环。
if param_get_ty(param_scan) is not None:
self.ensure_opaque_for_type(pool, param_get_ty(param_scan))
param_scan = param_get_next(param_scan)
func_scan = func_scan.Next
nt: NamedTypeNode | t.CPtr = self.NamedTypeHead
# 结构体定义缓冲区:48 字段 × ~50 字节/字段类型名 ≈ 2400 字节,4096 足够