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:
TermiNexus committed 2026-09-08 12:52:48 +08:00
1 parent 76d1ee6076
commit 0bda395ecc
20 files changed
+103 -463

No files matched your search

+58 -9
View File
@@ -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:
+38
View File
@@ -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
+6
View File
@@ -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})"