fix(translator,peephole): TPC 属性链解析修复与窥孔 T1-T3 收尾
- TPC(lib/core): 泛型父特化形参按声明类登记 var_struct_class; _find_struct_key 键归一支持方括号内嵌 sha 前缀; 字段探测失败不再冒泡 FuncGen fail-fast; cast 局部通用指针槽按静态类 bitcast; 属性解析失败附诊断 - 窥孔(includes/llvmlite/__function.vp): 窥孔移至 Renumber 前使输出 SSA 编号连续; T3 no-op bitcast 消除; T4(数组 bitcast->GEP)验证干扰返回类型收敛已移除 - 附调试打点与 1.log
This commit is contained in:
1 parent
76d1ee6076
commit
0bda395ecc
20 files changed
+103
-463
No files matched your search
@@ -652,7 +652,16 @@ class ExprAttrHandle(BaseHandle):
|
||||
Gen.class_member_bitoffsets[ClassName][AttrName] = bo
|
||||
return self._load_bitfield_member(ObjVal, ClassName, AttrName)
|
||||
|
||||
offset = Gen._get_member_offset(AttrName, ClassName)
|
||||
try:
|
||||
offset = Gen._get_member_offset(AttrName, ClassName)
|
||||
except KeyError as _ke:
|
||||
_vsc2: Any = getattr(Gen, 'var_struct_class', {}) or {}
|
||||
raise KeyError(
|
||||
f"{_ke} | [attr-diag] var={VarName} "
|
||||
f"var_struct_class={_vsc2.get(VarName)!r} "
|
||||
f"objval_pointee={getattr(getattr(ObjVal, 'type', None), 'pointee', None)!r} "
|
||||
f"node={self._ExprText(Node)!r} "
|
||||
f"base={self._ExprText(Node.value)!r}") from None
|
||||
# 检查 offset 是否超出实际结构体
|
||||
if isinstance(ObjVal.type, ir.PointerType):
|
||||
actual_pointee: Any = ObjVal.type.pointee
|
||||
@@ -763,8 +772,18 @@ class ExprAttrHandle(BaseHandle):
|
||||
return cdefine_result
|
||||
ObjVal: Any = self.HandleExprLlvm(Node.value)
|
||||
if not ObjVal or not isinstance(ObjVal.type, ir.PointerType):
|
||||
import sys as _sys1
|
||||
_sys1.stderr.write(
|
||||
f"[CHAIN-DBG] nested no-obj: node={self._ExprText(Node)!r} "
|
||||
f"inner={self._ExprText(Node.value)!r} objval_type={getattr(ObjVal, 'type', None)!r}\n")
|
||||
return None
|
||||
pointee: Any = ObjVal.type.pointee
|
||||
if not (isinstance(pointee, ir.IntType)
|
||||
or isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType))):
|
||||
import sys as _sys1b
|
||||
_sys1b.stderr.write(
|
||||
f"[CHAIN-DBG] nested unhandled-pointee: node={self._ExprText(Node)!r} "
|
||||
f"objval_type={ObjVal.type!r} pointee={pointee!r}\n")
|
||||
|
||||
# char* → struct* cast + 成员访问
|
||||
if isinstance(pointee, ir.IntType) and pointee.width == 8:
|
||||
@@ -788,23 +807,34 @@ class ExprAttrHandle(BaseHandle):
|
||||
AttrClassName = self._resolve_attr_parent_hint(Node.value, Gen)
|
||||
ResolvedKey: str | None = self._find_struct_key_for_class_hint(Gen, AttrClassName)
|
||||
if ResolvedKey is None or ResolvedKey not in Gen.structs:
|
||||
import sys as _sys2
|
||||
_sys2.stderr.write(
|
||||
f"[CHAIN-DBG] char* key-miss: node={self._ExprText(Node)!r} "
|
||||
f"attr_class={AttrClassName!r} resolved_key={ResolvedKey!r} "
|
||||
f"objval_type={ObjVal.type!r}\n")
|
||||
return None
|
||||
st: Any
|
||||
ok: bool
|
||||
st, ok = self._try_Load_struct_from_stub(Gen, ResolvedKey)
|
||||
if not isinstance(st, ir.IdentifiedStructType):
|
||||
import sys as _sys3
|
||||
_sys3.stderr.write(f"[CHAIN-DBG] char* not-struct: key={ResolvedKey!r} st={st!r}\n")
|
||||
return None
|
||||
if st.elements is None:
|
||||
# stub 仍 opaque(如跨模块泛型仅声明):走泛型特化候选访问
|
||||
spec_val: Any = self._try_access_opaque_generic_member(Gen, ObjVal, st, Node, ResolvedKey, AttrClassName)
|
||||
if spec_val is not None:
|
||||
return spec_val
|
||||
import sys as _sys4
|
||||
_sys4.stderr.write(f"[CHAIN-DBG] char* opaque-miss: key={ResolvedKey!r} node={self._ExprText(Node)!r}\n")
|
||||
return None
|
||||
CastedObj: Any = Gen.builder.bitcast(ObjVal, ir.PointerType(st), name=f"cast_{ResolvedKey}")
|
||||
if Node.attr in Gen.class_member_bitoffsets.get(ResolvedKey, {}):
|
||||
return self._load_bitfield_member(CastedObj, ResolvedKey, Node.attr)
|
||||
offset: int | None = Gen._get_member_offset(Node.attr, ResolvedKey)
|
||||
if offset is None:
|
||||
import sys as _sys5
|
||||
_sys5.stderr.write(f"[CHAIN-DBG] char* offset-miss: key={ResolvedKey!r} attr={Node.attr!r} st={st!r}\n")
|
||||
return None
|
||||
if offset < len(st.elements) and isinstance(st.elements[offset], ir.VoidType):
|
||||
return None
|
||||
@@ -833,7 +863,15 @@ class ExprAttrHandle(BaseHandle):
|
||||
bitfield_offsets: Any = Gen.class_member_bitoffsets.get(CN, {})
|
||||
if Node.attr in bitfield_offsets:
|
||||
return self._load_bitfield_member(ObjVal, CN, Node.attr)
|
||||
offset = Gen._get_member_offset(Node.attr, CN)
|
||||
try:
|
||||
offset = Gen._get_member_offset(Node.attr, CN)
|
||||
except KeyError as _ke2:
|
||||
raise KeyError(
|
||||
f"{_ke2} | [attr-diag-nested] "
|
||||
f"objval_pointee={getattr(getattr(ObjVal, 'type', None), 'pointee', None)!r} "
|
||||
f"node={self._ExprText(Node)!r} "
|
||||
f"inner={self._ExprText(Node.value)!r} "
|
||||
f"parent_hint={parent_hint!r}") from None
|
||||
if offset is None:
|
||||
break
|
||||
# 泛型基础类型字段特化(根本修复):
|
||||
@@ -1732,15 +1770,20 @@ class ExprAttrHandle(BaseHandle):
|
||||
"""把 class_member_element_class 记录的类/特化名解析为 Gen.structs 的真实键。
|
||||
|
||||
记录值可能是裸名('GSList[BasicBlock]')或带 sha1 前缀
|
||||
('8e92345fd262a343.GSList[BasicBlock]'),而 Gen.structs 的键可能是
|
||||
另一种形态。依次尝试:精确键 → 短名键 → class_sha1_map 重建前缀键 →
|
||||
遍历 Gen.structs 按短名匹配。
|
||||
('8e92345fd262a343.GSList[BasicBlock]'),且**方括号内元素也可能带模块
|
||||
前缀**('GSList[29fdb5e25dc949f4.BasicBlock]',跨模块泛型特化登记值)。
|
||||
Gen.structs 的键可能是另一种形态。比较前统一剥除所有 '<16hex>.' 片段:
|
||||
依次尝试:精确键 → 归一短名键 → class_sha1_map 重建前缀键 →
|
||||
遍历 Gen.structs 按归一短名匹配。
|
||||
"""
|
||||
if not ClassHint:
|
||||
return None
|
||||
if ClassHint in Gen.structs:
|
||||
return ClassHint
|
||||
short: str = Gen._extract_short_name(ClassHint)
|
||||
import re as _re_sha
|
||||
def _strip_sha(s: str) -> str:
|
||||
return _re_sha.sub(r'(?i)[0-9a-f]{16}\.', '', s)
|
||||
short: str = _strip_sha(Gen._extract_short_name(ClassHint))
|
||||
if short in Gen.structs:
|
||||
return short
|
||||
expected_sha1: str | None = (getattr(Gen, 'class_sha1_map', {}) or {}).get(short)
|
||||
@@ -1749,7 +1792,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
if prefixed in Gen.structs:
|
||||
return prefixed
|
||||
for key in Gen.structs:
|
||||
if Gen._extract_short_name(key) == short:
|
||||
if _strip_sha(Gen._extract_short_name(key)) == short:
|
||||
return key
|
||||
return None
|
||||
|
||||
@@ -1883,7 +1926,10 @@ class ExprAttrHandle(BaseHandle):
|
||||
ok_v: bool
|
||||
st_v, ok_v = self._try_Load_struct_from_stub(Gen, owner_key)
|
||||
if isinstance(st_v, ir.IdentifiedStructType) and st_v.elements is not None:
|
||||
off: int | None = Gen._get_member_offset(AttrName, owner_key)
|
||||
try:
|
||||
off: int | None = Gen._get_member_offset(AttrName, owner_key)
|
||||
except KeyError:
|
||||
off = None
|
||||
if off is not None and off < len(st_v.elements):
|
||||
k3: str | None = self._pointee_llvm_to_struct_key(Gen, st_v.elements[off])
|
||||
if k3:
|
||||
@@ -1898,7 +1944,10 @@ class ExprAttrHandle(BaseHandle):
|
||||
p_ok: bool
|
||||
p_st, p_ok = self._try_Load_struct_from_stub(Gen, p_key)
|
||||
if isinstance(p_st, ir.IdentifiedStructType) and p_st.elements is not None:
|
||||
p_off: int | None = Gen._get_member_offset(AttrName, p_key)
|
||||
try:
|
||||
p_off: int | None = Gen._get_member_offset(AttrName, p_key)
|
||||
except KeyError:
|
||||
p_off = None
|
||||
if p_off is not None and p_off < len(p_st.elements):
|
||||
k4: str | None = self._pointee_llvm_to_struct_key(Gen, p_st.elements[p_off])
|
||||
if k4:
|
||||
|
||||
@@ -1792,6 +1792,44 @@ class FunctionHandle(BaseHandle):
|
||||
found_struct: str | None = FindStructNameInAnnotation(arg.annotation, Gen.structs)
|
||||
if found_struct:
|
||||
Gen.var_struct_class[param_name] = found_struct
|
||||
# 普通类注解形参(非 BinOp 联合):rowptr[X] / t.CPtr[X] / X / t.X
|
||||
# 一律按"声明类"登记 var_struct_class。避免按 param.type.pointee 匹配
|
||||
# 到泛型父特化(如 class Function(GSListNode[Function]) 的形参 func 被
|
||||
# 登记成 GSListNode[Function],其 struct 仅含 Next → func.Blocks 访问
|
||||
# fast-fail "属性 'Blocks' 在类 'GSListNode[Function]' 中找不到")。
|
||||
# 泛型占位(rowptr[T])的 T 不在 Gen.structs,自动跳过、保留 pointee 匹配。
|
||||
for i, arg in enumerate(Node.args.args):
|
||||
if arg.annotation is None:
|
||||
continue
|
||||
if isinstance(arg.annotation, ast.BinOp) and isinstance(arg.annotation.op, ast.BitOr):
|
||||
continue # 联合注解由上方循环处理
|
||||
param_name = ParamNames[i] if i < len(ParamNames) else arg.arg
|
||||
if param_name not in Gen.variables:
|
||||
continue
|
||||
ann = arg.annotation
|
||||
target: str | None = None
|
||||
if isinstance(ann, ast.Name):
|
||||
target = ann.id
|
||||
elif isinstance(ann, ast.Attribute):
|
||||
target = ann.attr
|
||||
elif isinstance(ann, ast.Subscript):
|
||||
subv = ann.value
|
||||
subname = getattr(subv, 'id', None) or getattr(subv, 'attr', '')
|
||||
if subname in ('rowptr', 'CPtr', 'Ptr'):
|
||||
slc = ann.slice
|
||||
if isinstance(slc, ast.Name):
|
||||
target = slc.id
|
||||
elif isinstance(slc, ast.Attribute):
|
||||
target = slc.attr
|
||||
if not target:
|
||||
continue
|
||||
key: str | None = target if target in Gen.structs else None
|
||||
if key is None:
|
||||
_sha_t: str | None = (getattr(Gen, 'class_sha1_map', {}) or {}).get(target)
|
||||
if _sha_t and f'{_sha_t}.{target}' in Gen.structs:
|
||||
key = f'{_sha_t}.{target}'
|
||||
if key:
|
||||
Gen.var_struct_class[param_name] = key
|
||||
if ResolvedClassName and (IsMethod or RawFuncName == '__init__'):
|
||||
self.Trans._CurrentCpythonObjectClass = ResolvedClassName
|
||||
Gen._variadic_info = None
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import Any
|
||||
import vast as ast
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import llvmlite.ir as ir
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
@@ -502,6 +503,11 @@ class FuncGenMixin:
|
||||
if isinstance(_st_diag, ir.IdentifiedStructType):
|
||||
_struct_diag = f"{len(_st_diag.elements)} elems" if _st_diag.elements is not None else 'opaque'
|
||||
_member_names_diag: list = [n for n, _ in _members_diag][:16]
|
||||
try:
|
||||
import traceback as _tb
|
||||
_tb.print_stack(file=sys.stderr)
|
||||
except Exception:
|
||||
pass
|
||||
raise KeyError(
|
||||
f"[fast-fail] 属性 '{field_name}' 在类 '{ClassName}' 中找不到"
|
||||
f"(class_members={len(_members_diag)} 个: {_member_names_diag}, struct={_struct_diag})"
|
||||
|
||||
Reference in new issue
Block a user