fix(TPC): 泛型基础类型字段访问特化,修复 GSList.Head 返回泛型占位 T*
_handle_attr_nested 对声明为特化泛型(GSList[BasicBlock] | t.CPtr)的字段(如 Function.Blocks)访问 Head/Tail/Count 时,基础 GSList 有 body 直接按基础类型返回泛型占位 T*,AnnAssign 存储时变量被污染为 T*(var_struct_class 错设为 T),后续字段访问/while 循环体翻译静默失败 → llvmlite __function.vp _find_max_ssa_number/RenumberSSA 死循环(LLvmLiteTest Test 3 崩溃根因)。 修复:字段类型为泛型占位指针时,用 class_member_element_class 记录的特化版本 bitcast 后访问返回真实元素类型(如 BasicBlock*);AnnAssign 兜底跳过泛型占位参与变量类型重建,防其它 T* 场景污染。
This commit is contained in:
1 parent
3fd875daca
commit
d698fad162
2 files changed
+36
No files matched your search
@@ -623,6 +623,13 @@ class AnnAssignHandle(BaseHandle):
|
||||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||||
return
|
||||
for CN, ST in Gen.structs.items():
|
||||
# 泛型占位类型(T/U/V,如 GSList[T].Head 的元素类型)opaque 无 body,
|
||||
# 不参与变量类型重建/var_struct_class 设置:跟随 T* 会污染注解声明的
|
||||
# 真实类型(如 BasicBlock*),导致后续字段访问/循环体翻译静默失败。
|
||||
# (属性访问层已特化返回真实元素类型,此处为防御性兜底。)
|
||||
_cn_short: str = CN.split('.')[-1] if '.' in CN else CN
|
||||
if _IsGenericTpName(_cn_short):
|
||||
continue
|
||||
if pointee is ST or pointee == ST:
|
||||
# 若注解是泛型特化(如 ndarray[t.CDouble] | t.CPtr),
|
||||
# 构造正确的特化名(如 ndarray[double]),而非用 opaque 基础名
|
||||
|
||||
@@ -737,6 +737,35 @@ class ExprAttrHandle(BaseHandle):
|
||||
offset = Gen._get_member_offset(Node.attr, CN)
|
||||
if offset is None:
|
||||
break
|
||||
# 泛型基础类型字段特化(根本修复):
|
||||
# 当字段声明为特化泛型(如 GSList[BasicBlock])时,基础类型(GSList)的
|
||||
# Head/Tail/Count 字段类型是泛型占位 T*。直接按基础类型访问会返回 T*,
|
||||
# 导致变量类型被污染(后续字段访问/循环体翻译静默失败,见
|
||||
# llvmlite __function.vp _find_max_ssa_number 死循环根因)。
|
||||
# 用 class_member_element_class 记录的特化类型(parent_hint)重新访问,
|
||||
# 返回真实元素类型(如 BasicBlock*)。
|
||||
if (parent_hint is not None
|
||||
and isinstance(st, ir.IdentifiedStructType)
|
||||
and st.elements is not None and offset < len(st.elements)
|
||||
and isinstance(st.elements[offset], ir.PointerType)
|
||||
and isinstance(st.elements[offset].pointee, ir.IdentifiedStructType)):
|
||||
_field_short: str = (st.elements[offset].pointee.name or '').split('.')[-1]
|
||||
if (len(_field_short) == 1 and _field_short.isalpha() and _field_short.isupper()):
|
||||
_hint_short: str = parent_hint.split('.')[-1] if '.' in parent_hint else parent_hint
|
||||
for CN2, ST2 in Gen.structs.items():
|
||||
if not isinstance(ST2, ir.IdentifiedStructType):
|
||||
continue
|
||||
if ST2 is ST:
|
||||
continue
|
||||
if ST2.elements is None:
|
||||
continue
|
||||
_spec_short: str = CN2.split('.')[-1] if '.' in CN2 else CN2
|
||||
if _spec_short == _hint_short:
|
||||
_casted: Any = Gen.builder.bitcast(ObjVal, ir.PointerType(ST2), name=f"cast_spec_{CN}")
|
||||
_off2: int | None = Gen._get_member_offset(Node.attr, CN2)
|
||||
if _off2 is not None:
|
||||
return self._gep_and_Load_member(Gen, _casted, _off2, Node.attr, CN2, ST2)
|
||||
break
|
||||
return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st)
|
||||
return None
|
||||
|
||||
|
||||
Reference in new issue
Block a user