fix(gen): 裸名 CArray 类字段解析 + 跨模块函数返回类型 vpi 解析
- TypeGenMixin/HandlesAnnAssign: 支持 from t import * 后裸名 CArray[...]
(单参→Ptr(elem),双参→Array),修复 T4K3 类字段 CArray[str]=[...]
退化为 list[str] 动态构造 → list[str] 特化/append/_mbuddy 链接 undefined
- CallGenMixin: 跨模块函数调用返回类型按 vpi stub 注解解析
(tuple[T1,T2]→{T1,T2}),修复 b2a_hqx tuple 解包失效
This commit is contained in:
1 parent
304bece6fa
commit
b232c9266c
3 files changed
+91
-12
No files matched your search
@@ -6102,7 +6102,38 @@ class CallGenMixin:
|
||||
if found_ret_ty is not None:
|
||||
call_ret_ty: llvmlite.LLVMType | t.CPtr = found_ret_ty
|
||||
else:
|
||||
call_ret_ty = self._infer_external_func_ret_ty(pool, func_name)
|
||||
# found_func=None(跨模块 stub 未注入):先从 vpi stub 返回注解
|
||||
# 缓存精确获取返回类型(含 tuple[T1,T2] → 匿名结构体,如
|
||||
# b2a_hqx -> tuple[str, t.CUnsignedShort] → {i8*, i16}),
|
||||
# 未命中才回退 _infer_external_func_ret_ty 白名单推断。
|
||||
# 根因:_infer 白名单无 tuple 概念,未知函数默认 i32 会截断
|
||||
# 指针/i64;b2a_hqx 被推断为单值 i8*/i32 后调用侧返回值类型
|
||||
# 与定义侧 {i8*, i16} 不匹配 → HandlesAssign 的 tuple 解包
|
||||
# (依赖 rhs_val.Ty 是 Struct)静默跳过 → 目标变量从未赋值 →
|
||||
# free 未初始化栈垃圾指针崩溃(HashLibTest hqx 段)。
|
||||
vpi_ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
at_ret: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if at_ret.value is not None and at_ret.value.kind() == ast.ASTKind.Name:
|
||||
mod_ret_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_ret.value)
|
||||
if mod_ret_nm.id is not None:
|
||||
mod_ret_sha1: str = self._lookup_module_sha1(mod_ret_nm.id)
|
||||
if mod_ret_sha1 is not None:
|
||||
# 函数内懒 import:VpiReader imports HandlesExprCall,
|
||||
# 顶层 import 会成环(与 _lookup_method_ret_ty_via_vpi 一致)
|
||||
import lib.StubGen.VpiReader as VpiReader
|
||||
VpiReader._ensure_vpi_ret_annot_loaded(mod_ret_sha1, self.TempDir)
|
||||
ret_annot_fc: str = VpiReader._lookup_vpi_ret_annot(
|
||||
mod_ret_sha1, None, func_name)
|
||||
if ret_annot_fc is not None:
|
||||
vpi_ret_ty = VpiReader._resolve_vpi_ret_annot_str(
|
||||
pool, ret_annot_fc,
|
||||
llvmlite.Int32(pool),
|
||||
llvmlite.Ptr(pool, llvmlite.Int8(pool)))
|
||||
if vpi_ret_ty is not None:
|
||||
call_ret_ty = vpi_ret_ty
|
||||
else:
|
||||
call_ret_ty = self._infer_external_func_ret_ty(pool, func_name)
|
||||
|
||||
# 如果模块中找不到函数,检查是否是变量(函数指针 / 闭包调用)
|
||||
if found_func is None:
|
||||
|
||||
@@ -1955,6 +1955,42 @@ class TypeGenMixin:
|
||||
if sub.value.kind() == ast.ASTKind.Name:
|
||||
gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
|
||||
if gen_nm.id is not None:
|
||||
# 裸名 CArray(from t import * 场景,如 core.vp 的
|
||||
# `__python_suffix__: CArray[str] = ["py", ...]`):与 t.CArray
|
||||
# 语义等价。否则走泛型模板查找失败(CArray 不是泛型类模板)→
|
||||
# 字段类型退化 Ptr(i8) → __before_init__ 默认值 List 字面量误走
|
||||
# 动态 list 构造(list[str].__new__/append 符号未生成 → 链接
|
||||
# undefined reference,Termination4K3 链接失败根因)。
|
||||
if string.strcmp(gen_nm.id, "CArray") == 0:
|
||||
# 单参数: CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组)
|
||||
if sub.slice.kind() != ast.ASTKind.Tuple:
|
||||
elem_n: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type(
|
||||
pool, sub.slice, imported_modules, from_imports, trans)
|
||||
if elem_n is None:
|
||||
return None
|
||||
return llvmlite.Ptr(pool, elem_n)
|
||||
# 双参数: CArray[elem_ty, count] → [count x elem_ty]
|
||||
tup_n: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice)
|
||||
if tup_n.elts is None or tup_n.elts.__len__() < 2:
|
||||
return None
|
||||
elem_node_n: ast.AST | t.CPtr = tup_n.elts.get(0)
|
||||
count_node_n: ast.AST | t.CPtr = tup_n.elts.get(1)
|
||||
if elem_node_n is None or count_node_n is None:
|
||||
return None
|
||||
elem_ty_n: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type(
|
||||
pool, elem_node_n, imported_modules, from_imports, trans)
|
||||
if elem_ty_n is None:
|
||||
return None
|
||||
# count=None → Ptr(elem)(等价单参)
|
||||
if count_node_n.kind() == ast.ASTKind.Constant:
|
||||
cnt_n: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(count_node_n)
|
||||
if cnt_n.const_kind == ast.CONST_NONE:
|
||||
return llvmlite.Ptr(pool, elem_ty_n)
|
||||
count_n: int = self._eval_const_int_expr(
|
||||
count_node_n, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0 or count_n <= 0:
|
||||
return None
|
||||
return llvmlite.Array(pool, elem_ty_n, count_n)
|
||||
return self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans,
|
||||
imported_modules, from_imports)
|
||||
# 检查 value 是否是 Attribute(t.CArray / t.Callable / 模块限定泛型类如 numpy.ndarray[T])
|
||||
|
||||
@@ -171,23 +171,35 @@ def _is_ptr_element_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
# "单参数 list[type] → 指针,但如果有列表字面量初始化值则按数组 list[type, N] 处理")。
|
||||
# ============================================================
|
||||
def _is_single_param_carray_annot(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检查注解是否为单参/None 长度 t.CArray[...],返回 1=是 0=否"""
|
||||
"""检查注解是否为单参/None 长度 t.CArray[...],返回 1=是 0=否
|
||||
|
||||
支持两种书写形式:
|
||||
1. 模块限定 t.CArray[...](Attribute value)
|
||||
2. 裸名 CArray[...](from t import * 后使用,如 Termination4K3 core.vp
|
||||
的 `__python_suffix__: CArray[str] = ["py", ...]`)
|
||||
"""
|
||||
if annot is None or annot.kind() != ast.ASTKind.Subscript:
|
||||
return 0
|
||||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot)
|
||||
if sub.value is None or sub.slice is None:
|
||||
return 0
|
||||
if sub.value.kind() != ast.ASTKind.Attribute:
|
||||
if sub.value.kind() == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value)
|
||||
if at.attr is None or string.strcmp(at.attr, "CArray") != 0:
|
||||
return 0
|
||||
if at.value is None or at.value.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
mv: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if mv.id is None or string.strcmp(mv.id, "t") != 0:
|
||||
return 0
|
||||
elif sub.value.kind() == ast.ASTKind.Name:
|
||||
# 裸名 CArray(from t import *):与 t.CArray 等价
|
||||
bn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
|
||||
if bn.id is None or string.strcmp(bn.id, "CArray") != 0:
|
||||
return 0
|
||||
else:
|
||||
return 0
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value)
|
||||
if at.attr is None or string.strcmp(at.attr, "CArray") != 0:
|
||||
return 0
|
||||
if at.value is None or at.value.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
mv: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if mv.id is None or string.strcmp(mv.id, "t") != 0:
|
||||
return 0
|
||||
# 单参形式:slice 非 Tuple(如 t.CArray[u64])
|
||||
# 单参形式:slice 非 Tuple(如 t.CArray[u64] / CArray[str])
|
||||
if sub.slice.kind() != ast.ASTKind.Tuple:
|
||||
return 1
|
||||
# 双参形式:count=None(t.CArray[u64, None])→ 等价单参
|
||||
|
||||
Reference in new issue
Block a user