fix(LLVMCG): 尾部对齐加「前缀数 == 父类 struct 槽数」前置校验,修正 Generator.vp:136 误报
类别:a 编译器缺陷(TPC 侧;修正 b06dac1d 引入的过宽判据)
现象:翻译 TransPyV/App/lib/core/Gen/Generator.vp 时 `SubTypeGen.Gen = self`(:136)报
「指针隐式转换已禁止(非基本类型):不能把 %"47382dc8277c9d28.Generator"* 隐式转为
%"6fbe68e8fca81223.TypeSpecArena"*」。
判据(事实链):
· SubTypeGen 静态类型 = rawptr[TypeGenMixin.TypeGenMixin],Gen 字段声明在基类 TypeGenBase;
该 struct 41 槽:槽 0 = Generator*(Gen),槽 40 = TypeSpecArena*(Specs)。
· 抛错点 `_StoreWithCoerce` 用的是 **GEP 出来的槽类型**(TargetType = Ptr.type.pointee)
⇒ 报错里的 TypeSpecArena* 说明 "Gen 的偏移被算成了 40"(Specs 那一槽),而不是 0。
· 成因:b06dac1d 的「尾部对齐」在"成员表短于 body 字段区"时按 `len(elements) - len(表)`
求前缀数;TypeGenMixin 的表只有 ['Gen'] 一项(且其声明类型已退化成通用指针 ⇒
类型自校验被放行),于是被锚到 body 末尾 = 槽 40。
修法:尾部对齐加**必需的前缀校验**——前缀数必须等于**父类 struct 的槽数**(展平前缀就是
父类整份布局,含其继承链);父类 struct 不可得(跨模块未加载 / opaque)时**不介入**。
TypeGenMixin:40 ≠ len(TypeGenBase)=41 ⇒ 不介入,落回下标法得 0(Generator*,赋值合法)。
(正面场景仍生效:AnnAssign 表仅 4 项自有字段、body 12 槽、父类 Stmt 8 槽 ⇒ 8 == 8。)
验证:冒烟两例——反例 TypeGenMixin.Gen → 0(修前 40);正例 AnnAssign 仅自有字段表仍得
target/annotation/value/simple = 8/9/10/11;FuncGen py_compile 通过。
This commit is contained in:
1 parent
bd92dfdadf
commit
1776dfa60a
1 file changed
+16
-1
@@ -604,8 +604,23 @@ class FuncGenMixin:
|
|||||||
# _MemberSlotAccepts):表自洽(长度 == 字段区)时本路径不介入,
|
# _MemberSlotAccepts):表自洽(长度 == 字段区)时本路径不介入,
|
||||||
# 对既有正确行为零变化;REnum 是 max-variant 镜像布局,不适用。
|
# 对既有正确行为零变化;REnum 是 max-variant 镜像布局,不适用。
|
||||||
_FieldArea: int = len(_OffEls) - _BaseNow()
|
_FieldArea: int = len(_OffEls) - _BaseNow()
|
||||||
|
# 【前置校验·必需】尾部对齐只对"**缺父类前缀**"的表成立,判据是
|
||||||
|
# 前缀数 == 父类 struct 的槽数(展平前缀就是父类整份布局,含其继承链)。
|
||||||
|
# 缺了这条,一张**只含前若干字段**的残缺表会被锚到 body 末尾:
|
||||||
|
# 现场 `SubTypeGen.Gen = self`(Generator.vp:136)——TypeGenMixin 表
|
||||||
|
# 仅 ['Gen'](且其声明类型是通用指针/未解析),body 41 槽 ⇒ 被锚到
|
||||||
|
# 槽 40(= Specs,%TypeSpecArena*)⇒ 报"Generator* 不能隐式转
|
||||||
|
# TypeSpecArena*"。父类 struct 不可得(跨模块未加载/opaque)时
|
||||||
|
# **不介入**(保守落回配对 / 旧路径)。
|
||||||
|
_ParentCls: str | None = self.class_parent.get(_ResolvedClass)
|
||||||
|
_ParentSt: Any = self.structs.get(_ParentCls) if _ParentCls else None
|
||||||
|
_ParentLen: int = -1
|
||||||
|
if isinstance(_ParentSt, ir.IdentifiedStructType) and _ParentSt.elements is not None:
|
||||||
|
_ParentLen = len(_ParentSt.elements)
|
||||||
if (len(_OffMembers) < _FieldArea
|
if (len(_OffMembers) < _FieldArea
|
||||||
and not self._IsRenumLayoutClass(_ResolvedClass)):
|
and not self._IsRenumLayoutClass(_ResolvedClass)
|
||||||
|
and _ParentLen > 0
|
||||||
|
and len(_OffEls) - len(_OffMembers) == _ParentLen):
|
||||||
_TailBase: int = len(_OffEls) - len(_OffMembers)
|
_TailBase: int = len(_OffEls) - len(_OffMembers)
|
||||||
_TailOk: bool = _TailBase >= 0
|
_TailOk: bool = _TailBase >= 0
|
||||||
_iT: int = 0
|
_iT: int = 0
|
||||||
|
|||||||
Reference in new issue
Block a user