fix(Handles*): GEP 基址 opaque pointee 收口统一为单一判据源,补齐同族 12 处缺口
【a 编译器缺陷】7aa12263 修好 `_get_attr_ptr` 的 self 分支后,同族其余 GEP 点仍会在
"基址 pointee 是另一份 opaque 同名实例"时抛裸 TypeError(被 IR 边界守卫拦下,报文为
"GEP 的基址指向**未具化**的具名结构体")。根因是同一套收口逻辑被各点各写一份、且
**多数点根本没写**:真正需要的判据只有一条。
新增唯一判据源(HandlesExprAttr):
· `_ConcretePointeeFor(Gen, ClassName, Pointee)`:取该类的**已具化实例** ——
① 类键那份先 `_TryLoadStructFromStub` 补 body;② 否则 `Gen._FindConcreteTwin`
(同短名、槽数最多);③ 都取不到 ⇒ None(**不兜底**,交守卫 fail-fast 报同短名
实例清单 + TPC 发射点)。
· `_ConcretizeGepBase(Gen, Ptr, ClassName, Tag)`:pointee 非 opaque ⇒ 原样返回
(对既有正确路径零变化);opaque ⇒ bitcast 到已具化实例并**同时返回该实例**,
供 `_get_member_offset` 作 StructHint(偏移与 GEP 必须同源,与 a43513c9 同口径)。
接入点(全部改为调用上述判据源,逐点行为只在"原本必崩"的情形下变化):
· HandlesExprAttr._get_attr_ptr — self / 变量 / 属性链 / i8* / 下标 / 强转基座 六条分支
(self 分支已由 7aa12263 修,此处并入统一判据;下标分支此前**完全没有**收口);
· HandlesAnnAssign._HandleAttributeStoreLlvm — self / 变量 / 属性链 三条分支;
· HandlesBase._get_int_ptr — 属性分支;
· HandlesExprBuiltin(len() 的两个接收者 GEP:`obj.len` 与 list 特化字段);
· HandlesMatch — REnum 变体 match 的载荷 GEP(变体 struct 可能未 set_body)。
冒烟(临时脚本已删,鸭子类型 Gen + 真实方法):
· `_get_attr_ptr` self 分支 ⇒ 基址 `%"fef783da4d24330d.Keyword"*`(经 cast_self_Keyword)PASS;
· `_get_attr_ptr` i8* 分支 ⇒ 同上 PASS;
· `HandlesAnnAssign` self 分支 ⇒ GEP 基址为已具化实例 PASS;
· 回归:基址本就具化时必须**原样**(不得多出 bitcast)PASS。
另:`python -m compileall TransPyC/lib` 全绿。
This commit is contained in:
1 parent
7aa12263f5
commit
00edd90c28
5 files changed
+133
-60
No files matched your search
@@ -96,9 +96,16 @@ class AnnAssignHandle(BaseHandle):
|
||||
SelfVar: ir.Value | None = Gen._get_var_ptr('self')
|
||||
if SelfVar:
|
||||
SelfPtr: ir.Value = Gen._load(SelfVar, name="self")
|
||||
offset: int = Gen._get_member_offset(AttrName, ClassName)
|
||||
MemberPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
# 基址收口(判据见 ExprAttrHandle._ConcretizeGepBase):self 的 pointee
|
||||
# 可能是**另一份 opaque 同名实例**(函数签名那份),typed pointer 下
|
||||
# GEP 必须编译期算出元素类型 ⇒ 先补 body / 取同短名孪生体再 GEP。
|
||||
_SP: Any
|
||||
SelfPtr, _SP = self.Trans.ExprAttrHandle._ConcretizeGepBase(
|
||||
Gen, SelfPtr, ClassName, f"cast_self_{ClassName}")
|
||||
offset: int = Gen._get_member_offset(AttrName, ClassName, _SP)
|
||||
if offset is not None:
|
||||
MemberPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
elif isinstance(Target.value, ast.Name):
|
||||
VarName: str = Target.value.id
|
||||
|
||||
@@ -193,6 +200,12 @@ class AnnAssignHandle(BaseHandle):
|
||||
and '[' in ClassName):
|
||||
ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_spec_{ClassName}")
|
||||
if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]:
|
||||
# 基址收口(判据见 ExprAttrHandle._ConcretizeGepBase):类键那份可能
|
||||
# 仍是 opaque(body 未 set_body / 另一份实例已具化)⇒ 先补 body /
|
||||
# 取同短名孪生体,偏移与 GEP 同源。
|
||||
_STa: Any
|
||||
ObjVal, _STa = self.Trans.ExprAttrHandle._ConcretizeGepBase(
|
||||
Gen, ObjVal, ClassName, f"cast_{ClassName}")
|
||||
if IsUnion:
|
||||
NestedStructName: str = f"{ClassName}_{AttrName}"
|
||||
if NestedStructName in Gen.structs:
|
||||
@@ -203,9 +216,10 @@ class AnnAssignHandle(BaseHandle):
|
||||
MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
return
|
||||
offset: int = Gen._get_member_offset(AttrName, ClassName)
|
||||
MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
offset: int = Gen._get_member_offset(AttrName, ClassName, _STa)
|
||||
if offset is not None:
|
||||
MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
elif isinstance(Target.value, ast.Attribute):
|
||||
ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||||
if ObjVal and isinstance(ObjVal.type, ir.PointerType):
|
||||
@@ -213,9 +227,14 @@ class AnnAssignHandle(BaseHandle):
|
||||
if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
|
||||
for CN, ST in Gen.structs.items():
|
||||
if pointee == ST:
|
||||
offset: int = Gen._get_member_offset(AttrName, CN)
|
||||
MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
# 基址收口(判据见 ExprAttrHandle._ConcretizeGepBase)
|
||||
_STb: Any
|
||||
ObjVal, _STb = self.Trans.ExprAttrHandle._ConcretizeGepBase(
|
||||
Gen, ObjVal, CN, f"cast_{CN}")
|
||||
offset: int = Gen._get_member_offset(AttrName, CN, _STb)
|
||||
if offset is not None:
|
||||
MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||||
self._StoreWithCoerce(Value, MemberPtr)
|
||||
break
|
||||
|
||||
def _StoreWithCoerce(self, Value: ir.Value, Ptr: ir.Value, Node: ast.AST | None = None) -> None:
|
||||
|
||||
@@ -810,7 +810,12 @@ class BaseHandle:
|
||||
StructName = ClassName
|
||||
break
|
||||
if StructName and StructName in Gen.structs:
|
||||
offset: int = self.Trans.ExprHandler._get_llvm_member_offset(Node.attr, StructName, Gen)
|
||||
# 基址收口(判据见 ExprAttrHandle._ConcretizeGepBase):pointee 可能是
|
||||
# **另一份 opaque 同名实例**,typed pointer 下 GEP 必须编译期算出
|
||||
# 元素类型 ⇒ 先补 body / 取同短名孪生体,并以该实例算偏移(同源)。
|
||||
obj_val, _STk = self.Trans.ExprAttrHandle._ConcretizeGepBase(
|
||||
Gen, obj_val, StructName, f"cast_{StructName}")
|
||||
offset: int = Gen._get_member_offset(Node.attr, StructName, _STk)
|
||||
member_ptr: Any = Gen.builder.gep(obj_val, [_ir.Constant(_ir.IntType(32), 0), _ir.Constant(_ir.IntType(32), offset)], name=f"{Node.attr}_ptr")
|
||||
return member_ptr
|
||||
return None
|
||||
|
||||
@@ -1772,6 +1772,54 @@ class ExprAttrHandle(BaseHandle):
|
||||
|
||||
# ========== _get_attr_ptr / _get_int_ptr / _get_attr_class ==========
|
||||
|
||||
def _ConcretePointeeFor(self, Gen: LlvmCodeGenerator, ClassName: str | None,
|
||||
Pointee: Any) -> Any:
|
||||
"""取该类的**已具化实例**(GEP 基址可用的那份):类键那份 → 同短名孪生体 → None。
|
||||
|
||||
为什么需要:同一类名常有两份 struct 实例(短名 'Keyword' / sha1 全名
|
||||
'<sha1>.Keyword'),"函数签名里的 self 用哪一份"与"StructGen 具化的是哪一份"
|
||||
并不保证一致;typed pointer 下 GEP 必须在**编译期**从 pointee 算元素类型,
|
||||
撞 opaque 即抛裸 TypeError('NoneType' object is not subscriptable)。
|
||||
|
||||
判据(全仓同族点同一套,不引入新判据):
|
||||
① 类键那份(`Gen.structs[ClassName]`)可经 `_TryLoadStructFromStub` 补出 body;
|
||||
② 否则按**同短名**取一份已具化实例(`Gen._FindConcreteTwin`,槽数最多);
|
||||
③ 都拿不到 ⇒ None(**不兜底**,交 IR 边界守卫 fail-fast 报同短名实例清单)。
|
||||
"""
|
||||
_Twin: Any = None
|
||||
if ClassName:
|
||||
_ST: Any = Gen.structs.get(ClassName)
|
||||
if isinstance(_ST, ir.IdentifiedStructType) and not _ST.elements:
|
||||
self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen)
|
||||
_ST = Gen.structs.get(ClassName, _ST)
|
||||
if isinstance(_ST, ir.IdentifiedStructType) and _ST.elements:
|
||||
_Twin = _ST
|
||||
if _Twin is None and isinstance(Pointee, ir.IdentifiedStructType):
|
||||
try:
|
||||
_Twin = Gen._FindConcreteTwin(Pointee)
|
||||
except Exception:
|
||||
_Twin = None
|
||||
return _Twin
|
||||
|
||||
def _ConcretizeGepBase(self, Gen: LlvmCodeGenerator, Ptr: Any, ClassName: str | None,
|
||||
Tag: str) -> tuple[Any, Any]:
|
||||
"""GEP 基址收口:pointee 为 **opaque** 具名结构体时 bitcast 到已具化实例。
|
||||
|
||||
判据与实例来源见 `_ConcretePointeeFor`;返回 `(基址指针, 该类的已具化实例)`,
|
||||
第二个返回值同时用作 `_get_member_offset` 的 StructHint —— 偏移与 GEP 必须同源
|
||||
(hint 只接受同类,见 FuncGen._member_base)。pointee 非 opaque 时原样返回,
|
||||
对既有正确路径零变化;都取不到实例时同样原样返回(不兜底,由守卫报根因)。
|
||||
"""
|
||||
if not isinstance(getattr(Ptr, 'type', None), ir.PointerType):
|
||||
return Ptr, None
|
||||
_Pointee: Any = Ptr.type.pointee
|
||||
if not isinstance(_Pointee, ir.IdentifiedStructType) or _Pointee.elements is not None:
|
||||
return Ptr, _Pointee
|
||||
_Twin: Any = self._ConcretePointeeFor(Gen, ClassName, _Pointee)
|
||||
if _Twin is None:
|
||||
return Ptr, _Pointee
|
||||
return (Gen.builder.bitcast(Ptr, ir.PointerType(_Twin), name=Tag), _Twin)
|
||||
|
||||
def _get_attr_ptr(self, Node: ast.Attribute) -> ir.Value | None:
|
||||
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
|
||||
if not isinstance(Node, ast.Attribute):
|
||||
@@ -1785,36 +1833,13 @@ class ExprAttrHandle(BaseHandle):
|
||||
if SelfVar:
|
||||
SelfPtr: Any = Gen._load(SelfVar, name="self")
|
||||
if isinstance(SelfPtr.type, ir.PointerType):
|
||||
# 基址 pointee 若**未具化**(opaque):typed pointer 下 GEP 必须
|
||||
# 在编译期算出元素类型,否则 llvmlite 内部抛裸 TypeError
|
||||
# ('NoneType' object is not subscriptable)。与**同函数下方
|
||||
# 各分支**(属性链分支 / i8* 分支:均先 _TryLoadStructFromStub
|
||||
# 补 body、再 bitcast 到已具化实例)同口径 —— 偏移与 GEP 必须
|
||||
# 同源;本分支此前是唯一漏了这套处理的分支。
|
||||
# 现场(2026-09-30):includes/ast/astaux.vp:165
|
||||
# `self.arg = _copy_str(pool, arg)`,GEP 名 'arg',基址 pointee
|
||||
# 是 opaque 的 `%"8312ce86a2fd82c0.Keyword"*`,而同短名的
|
||||
# 'Keyword' 键上那份已具化(10 槽)。
|
||||
_SelfPointee: Any = SelfPtr.type.pointee
|
||||
if (isinstance(_SelfPointee, ir.IdentifiedStructType)
|
||||
and _SelfPointee.elements is None):
|
||||
_ST: Any = Gen.structs.get(ClassName)
|
||||
if isinstance(_ST, ir.IdentifiedStructType) and not _ST.elements:
|
||||
self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen)
|
||||
_ST = Gen.structs.get(ClassName, _ST)
|
||||
_Twin: Any = None
|
||||
if isinstance(_ST, ir.IdentifiedStructType) and _ST.elements:
|
||||
_Twin = _ST
|
||||
else:
|
||||
try:
|
||||
_Twin = Gen._FindConcreteTwin(_SelfPointee)
|
||||
except Exception:
|
||||
_Twin = None
|
||||
if _Twin is not None:
|
||||
SelfPtr = Gen.builder.bitcast(
|
||||
SelfPtr, ir.PointerType(_Twin),
|
||||
name=f"cast_self_{ClassName}")
|
||||
_SelfPointee = _Twin
|
||||
# 基址收口(见 _ConcretizeGepBase):opaque 基址先补 body/取孪生体
|
||||
# 再 GEP。现场(2026-09-30):includes/ast/astaux.vp:165
|
||||
# `self.arg = _copy_str(pool, arg)`,GEP 名 'arg',基址 pointee 是
|
||||
# opaque 的 %"8312ce86a2fd82c0.Keyword"*,而同短名的 'Keyword'
|
||||
# 键上那份已具化(10 槽)。
|
||||
SelfPtr, _SelfPointee = self._ConcretizeGepBase(
|
||||
Gen, SelfPtr, ClassName, f"cast_self_{ClassName}")
|
||||
offset: int | None = Gen._get_member_offset(Node.attr, ClassName, _SelfPointee)
|
||||
if offset is None:
|
||||
return None
|
||||
@@ -1851,14 +1876,11 @@ class ExprAttrHandle(BaseHandle):
|
||||
if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType):
|
||||
ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}")
|
||||
if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]:
|
||||
ST: Any = Gen.structs[ClassName]
|
||||
if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0):
|
||||
self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen)
|
||||
ST = Gen.structs.get(ClassName, ST)
|
||||
if ST.elements is not None and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None:
|
||||
ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{ClassName}")
|
||||
offset = Gen._get_member_offset(Node.attr, ClassName)
|
||||
if offset is not None and ST.elements is not None:
|
||||
# 基址收口(见 _ConcretizeGepBase):类键那份可能仍 opaque ⇒ 补 body /
|
||||
# 取同短名孪生体后再 GEP(偏移同源)。
|
||||
ObjVal, ST = self._ConcretizeGepBase(Gen, ObjVal, ClassName, f"cast_{ClassName}")
|
||||
offset = Gen._get_member_offset(Node.attr, ClassName, ST)
|
||||
if offset is not None and isinstance(ST, ir.IdentifiedStructType) and ST.elements is not None:
|
||||
MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr)
|
||||
return MemberPtr
|
||||
elif isinstance(Node.value, ast.Attribute):
|
||||
@@ -1871,20 +1893,21 @@ class ExprAttrHandle(BaseHandle):
|
||||
CN: str
|
||||
ST: Any
|
||||
CN, ST = found
|
||||
if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0):
|
||||
self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen)
|
||||
ST = Gen.structs.get(CN, ST)
|
||||
if ST.elements is not None and isinstance(InnerPtr.type, ir.PointerType) and isinstance(InnerPtr.type.pointee, ir.IdentifiedStructType) and InnerPtr.type.pointee.elements is None:
|
||||
InnerPtr = Gen.builder.bitcast(InnerPtr, ir.PointerType(ST), name=f"cast_{CN}")
|
||||
offset = Gen._get_member_offset(Node.attr, CN)
|
||||
if offset is not None and ST.elements is not None:
|
||||
# 基址收口(见 _ConcretizeGepBase):链尾 pointee 可能仍是类键上那份
|
||||
# opaque 实例 ⇒ 补 body / 取同短名孪生体后再 GEP(偏移同源)。
|
||||
InnerPtr, ST = self._ConcretizeGepBase(Gen, InnerPtr, CN, f"cast_{CN}")
|
||||
offset = Gen._get_member_offset(Node.attr, CN, ST)
|
||||
if offset is not None and isinstance(ST, ir.IdentifiedStructType) and ST.elements is not None:
|
||||
MemberPtr = Gen.builder.gep(InnerPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr)
|
||||
return MemberPtr
|
||||
elif isinstance(pointee, ir.IntType) and pointee.width == 8:
|
||||
AttrClassName: str | None = self._get_attr_class(Node.value, Gen)
|
||||
if AttrClassName and AttrClassName in Gen.structs:
|
||||
CastedObj: Any = Gen.builder.bitcast(InnerPtr, ir.PointerType(Gen.structs[AttrClassName]), name=f"cast_{AttrClassName}")
|
||||
offset = Gen._get_member_offset(Node.attr, AttrClassName)
|
||||
# 类键那份可能仍 opaque ⇒ 统一收口(见 _ConcretizeGepBase)
|
||||
CastedObj, ST2 = self._ConcretizeGepBase(
|
||||
Gen, CastedObj, AttrClassName, f"cast_twin_{AttrClassName}")
|
||||
offset = Gen._get_member_offset(Node.attr, AttrClassName, ST2)
|
||||
if offset is not None:
|
||||
MemberPtr = Gen.builder.gep(CastedObj, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr)
|
||||
return MemberPtr
|
||||
@@ -1896,7 +1919,9 @@ class ExprAttrHandle(BaseHandle):
|
||||
found = Gen.find_struct_by_pointee(pointee)
|
||||
if found:
|
||||
CN, ST = found
|
||||
offset = Gen._get_member_offset(Node.attr, CN)
|
||||
# 基址收口(本分支此前完全没有这一步:opaque 时 GEP 直接抛裸 TypeError)
|
||||
SubPtr, ST = self._ConcretizeGepBase(Gen, SubPtr, CN, f"cast_{CN}")
|
||||
offset = Gen._get_member_offset(Node.attr, CN, ST)
|
||||
if offset is not None:
|
||||
MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr)
|
||||
return MemberPtr
|
||||
@@ -1917,6 +1942,13 @@ class ExprAttrHandle(BaseHandle):
|
||||
if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0):
|
||||
self.Trans.ImportHandler._TryLoadStructFromStub(UnionCls, Gen)
|
||||
ST = Gen.structs.get(UnionCls, ST)
|
||||
if isinstance(ST, ir.IdentifiedStructType) and not ST.elements:
|
||||
# 类键那份仍 opaque(body 未 set_body / 另一份实例已具化)⇒ 取已具化
|
||||
# 实例作目标 pointee,否则 bitcast/inttoptr 出来的基址仍是 opaque、
|
||||
# GEP 在编译期算不出元素类型(判据见 _ConcretePointeeFor)。
|
||||
_TwU: Any = self._ConcretePointeeFor(Gen, UnionCls, ST)
|
||||
if _TwU is not None:
|
||||
ST = _TwU
|
||||
TargetPtrTy: Any = ir.PointerType(ST)
|
||||
if isinstance(ObjVal.type, ir.PointerType):
|
||||
if ObjVal.type != TargetPtrTy:
|
||||
|
||||
@@ -648,7 +648,13 @@ class ExprBuiltinHandle(BaseHandle):
|
||||
self_val = Gen._get_var_ptr(obj_name)
|
||||
if self_val:
|
||||
self_ptr = Gen._load(self_val, name="obj_for_len")
|
||||
offset = Gen._get_member_offset(len_member, bare_cls)
|
||||
# 基址收口(判据见 ExprAttrHandle._ConcretizeGepBase):接收者的
|
||||
# pointee 可能是**另一份 opaque 同名实例**,GEP 需要在编译期算出
|
||||
# 元素类型 ⇒ 先补 body / 取同短名孪生体,并以该实例算偏移(同源)。
|
||||
_STl: Any
|
||||
self_ptr, _STl = self.Trans.ExprAttrHandle._ConcretizeGepBase(
|
||||
Gen, self_ptr, bare_cls, f"cast_{bare_cls}")
|
||||
offset = Gen._get_member_offset(len_member, bare_cls, _STl)
|
||||
len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{obj_name}_{len_member}_ptr")
|
||||
return Gen._load(len_ptr, name=f"{obj_name}_{len_member}")
|
||||
# 修复 stdint.vp 崩溃(0xC0000005)根因:`list[X] | t.CPtr` 联合字段
|
||||
@@ -672,7 +678,11 @@ class ExprBuiltinHandle(BaseHandle):
|
||||
self_val = Gen._get_var_ptr(obj_name)
|
||||
if self_val:
|
||||
self_ptr = Gen._load(self_val, name="obj_for_len")
|
||||
offset = Gen._get_member_offset(attr_name, bare_cls)
|
||||
# 基址收口(判据见 ExprAttrHandle._ConcretizeGepBase)
|
||||
_STl2: Any
|
||||
self_ptr, _STl2 = self.Trans.ExprAttrHandle._ConcretizeGepBase(
|
||||
Gen, self_ptr, bare_cls, f"cast_{bare_cls}")
|
||||
offset = Gen._get_member_offset(attr_name, bare_cls, _STl2)
|
||||
if offset is not None:
|
||||
list_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{obj_name}_{attr_name}_ptr")
|
||||
list_val = Gen._load(list_ptr, name=f"{obj_name}_{attr_name}")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Any
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.translator import Translator
|
||||
from lib.core.Handles.HandlesBase import BaseHandle
|
||||
@@ -439,6 +439,13 @@ class MatchHandle(BaseHandle):
|
||||
NestedStructName: str = f"{RenumName}_{VariantName}"
|
||||
if NestedStructName in Gen.structs:
|
||||
NestedStructType: ir.Type = Gen.structs[NestedStructName]
|
||||
# 变体 struct 可能仍是 opaque(body 未 set_body / 同名两份实例)
|
||||
# ⇒ 先取已具化实例,否则 GEP 在编译期算不出元素类型(判据见
|
||||
# ExprAttrHandle._ConcretePointeeFor)。
|
||||
_TwV: Any = self.Trans.ExprAttrHandle._ConcretePointeeFor(
|
||||
Gen, NestedStructName, NestedStructType)
|
||||
if isinstance(_TwV, ir.IdentifiedStructType):
|
||||
NestedStructType = _TwV
|
||||
NestedStructPtrType: ir.PointerType = ir.PointerType(NestedStructType)
|
||||
variant_ptr: ir.Value = Gen.builder.bitcast(SubjectPtr, NestedStructPtrType, name=f"match_cast_{VariantName}")
|
||||
for bind_name, member_name, member_type, member_idx in bindings:
|
||||
|
||||
Reference in new issue
Block a user