依据 T97 决定性结果,修复了 CVoid 严格验证,other_ty 有效性验证,fallback 不依赖 kind() 实现
This commit is contained in:
1 parent
f440bda421
commit
c876df7907
2 files changed
+85
-2
No files matched your search
@@ -152,8 +152,25 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy | t.CPtr,
|
||||
ast._lexer_init(lx, vpi_buf, pool)
|
||||
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
|
||||
tree: ast.AST | t.CPtr = ast.parse_tokens(pool, tokens)
|
||||
stdlib.free(vpi_buf)
|
||||
# vpi_buf 延迟释放:AST 字符串字段可能引用 vpi_buf 内部(token 零拷贝),
|
||||
# 提前 free 会导致 Name.id/Attribute.attr 等悬空 → 后续解析返回错误类型。
|
||||
# 在 ParseVpiIntoModule 末尾统一释放。
|
||||
# [DBG-T96] 临时诊断:定位 vpi AST 有效性(定位后移除)
|
||||
k96: int = -1
|
||||
if tree is not None:
|
||||
k96 = tree.kind()
|
||||
stdio.printf("[DBG-T96] vpi tree kind=%d children=", k96)
|
||||
if tree is not None and tree.children is not None:
|
||||
n96: t.CSizeT = tree.children.__len__()
|
||||
stdio.printf("%d\n", n96)
|
||||
if n96 > 0:
|
||||
c96: ast.AST | t.CPtr = tree.children.get(0)
|
||||
if c96 is not None:
|
||||
stdio.printf("[DBG-T96] child0 kind=%d\n", c96.kind())
|
||||
else:
|
||||
stdio.printf("0\n")
|
||||
if tree is None:
|
||||
stdlib.free(vpi_buf)
|
||||
return 0
|
||||
|
||||
# 提取源模块 SHA1(用于函数名混淆,在 AST 解析成功后提取避免提前返回时泄漏)
|
||||
@@ -234,6 +251,8 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 释放 SHA1 缓冲区(_extract_sha1_from_path 用 stdlib.malloc 分配)
|
||||
if src_sha1 is not None:
|
||||
stdlib.free(src_sha1)
|
||||
# vpi_buf 延迟到全部 tree 处理完成后释放(见解析处注释)
|
||||
stdlib.free(vpi_buf)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -420,6 +439,26 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
if ret_ty is None:
|
||||
ret_ty = i32_ty
|
||||
|
||||
# [DBG-T97] 临时诊断:定位 args.get_str 类型退化(定位后移除)
|
||||
if string.strcmp(m_fd.name, "parse_args") == 0:
|
||||
vis97: int = HandlesStruct.is_struct_visible("ParsedArgs")
|
||||
gst97: t.CChar | t.CPtr = stdlib.malloc(128)
|
||||
if gst97 is not None:
|
||||
gty97: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type("ParsedArgs")
|
||||
if gty97 is not None:
|
||||
llvmlite.TypePrint(gst97, 128, gty97, pool)
|
||||
else:
|
||||
viperlib.snprintf(gst97, 128, "NULL")
|
||||
ot97: t.CChar | t.CPtr = stdlib.malloc(128)
|
||||
if ot97 is not None:
|
||||
if ret_ty is not None:
|
||||
llvmlite.TypePrint(ot97, 128, ret_ty, pool)
|
||||
else:
|
||||
viperlib.snprintf(ot97, 128, "NULL")
|
||||
stdio.printf("[DBG-T97] vis=%d gst=%s ret=%s\n", vis97, gst97, ot97)
|
||||
stdlib.free(ot97)
|
||||
stdlib.free(gst97)
|
||||
|
||||
# 创建 declare
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||||
pool, mod, mangled_name, ret_ty)
|
||||
|
||||
@@ -1550,12 +1550,56 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
if left_is_cptr != 0:
|
||||
other_node = bop.right
|
||||
# 检测另一边是否是 t.CVoid (void* = i8*)
|
||||
other_is_cvoid: int = _is_cvoid_marker(other_node, imported_modules)
|
||||
# 严格验证完整形式(Attribute(t.CVoid) 的 value 是 Name("t"),
|
||||
# 或裸名 CVoid 且 t 已导入),防止解析异常节点被误判为 CVoid。
|
||||
other_is_cvoid: int = 0
|
||||
if other_node is not None:
|
||||
if other_node.kind() == ast.ASTKind.Attribute:
|
||||
oat2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(other_node)
|
||||
if oat2.attr is not None and string.strcmp(oat2.attr, "CVoid") == 0:
|
||||
if oat2.value is not None and oat2.value.kind() == ast.ASTKind.Name:
|
||||
ov2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(oat2.value)
|
||||
if ov2.id is not None and string.strcmp(ov2.id, "t") == 0:
|
||||
other_is_cvoid = 1
|
||||
elif other_node.kind() == ast.ASTKind.Name:
|
||||
onm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node)
|
||||
if onm2.id is not None and string.strcmp(onm2.id, "CVoid") == 0:
|
||||
if HandlesImports.is_module_imported(imported_modules, "t") != 0:
|
||||
other_is_cvoid = 1
|
||||
if other_is_cvoid != 0:
|
||||
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
other_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
|
||||
pool, other_node, imported_modules, from_imports, trans)
|
||||
# other_ty 必须是已注册的结构体类型才算有效:
|
||||
# X | t.CPtr 的 X 是类名,解析结果应为 struct 类型。
|
||||
# 若节点异常导致解析出基础类型/垃圾(如 Int8 → Ptr(i8)),
|
||||
# 不应直接返回,需走下方回退按类名查全局表。
|
||||
# (str | t.CPtr 解析为 Ptr(i8) 非 struct,回退 get_struct_type
|
||||
# 查不到 str → 仍返回 Ptr(i8),结果一致,不受影响。)
|
||||
if other_ty is not None:
|
||||
if HandlesStruct.find_struct_by_type(other_ty) is not None:
|
||||
return llvmlite.Ptr(pool, other_ty)
|
||||
other_ty = None
|
||||
if other_ty is None:
|
||||
# 严格模式(App 文件)下裸类名不可见时,回退到全局
|
||||
# struct 注册表按类名查找。X | t.CPtr 是明确的指针包装
|
||||
# 注解(如 vpi stub 的 "ParsedArgs | t.CPtr"),X 已注册
|
||||
# 时不应静默退化为 i8*——i8* 会让方法返回值的无注解变量
|
||||
# (如 args = parser.parse_args())类型退化,后续 obj.method
|
||||
# get_class_name_by_type 查不到类名,误报
|
||||
# "跨模块调用 'args.get_str' 找不到模块 SHA1"。
|
||||
# 不检查 kind():vpi 解析的节点在后续处理中可能已损坏
|
||||
# (kind() 读取异常),直接按 Name 布局读取 id,
|
||||
# 由 get_struct_type 兜底校验(无效类名返回 None)。
|
||||
other_cls_nm: str = None
|
||||
if other_node is not None:
|
||||
other_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node)
|
||||
if other_nm.id is not None:
|
||||
other_cls_nm = other_nm.id
|
||||
if other_cls_nm is not None:
|
||||
other_cls_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(other_cls_nm)
|
||||
if other_cls_ty is not None:
|
||||
return llvmlite.Ptr(pool, other_cls_ty)
|
||||
# CPtr 单独使用或其他无效类型 → i8*
|
||||
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
return llvmlite.Ptr(pool, other_ty)
|
||||
|
||||
Reference in new issue
Block a user