fix(classdef): 值类型字段补完整结构体定义,修复跨模块嵌套结构体 unsized 导致 llc GEP 报错

现场:Test/ThreadingTest 编译 includes/condition.vp 时 llc 报「base element of getelementptr must be sized」:getelementptr %Condition, %Condition* %1, i32 0, i32 1。

根因:ClassGenDef 定义类时对字段类型一律只调 module_ensure_opaque_for_type(仅 opaque 声明)。当字段是**值类型**跨模块结构体时,本类体内嵌的成员在 IR 中仍是 opaque ⇒ 成员 unsized ⇒ 本类 unsized ⇒ 本模块内对本类做带字段下标的 GEP 时 llc 报错。现场物证:condition.vp 的 .ll 里 CONDITION_VARIABLE/CRITICAL_SECTION = type opaque,而 Condition = type {CV, CS}。

修复:指针字段维持 opaque(指向物无需在本模块有体);非指针(值类型结构体/结构体数组)改调 ensure_struct_def_in_module 复制完整定义,并配合 _ensure_field_types_in_module 覆盖数组元素。
This commit is contained in:
TermiNexus committed 2026-10-03 15:58:48 +08:00
1 parent 28b7437e21
commit 96dad309ac
1 file changed
+15 -2
+15 -2
View File
@@ -577,14 +577,27 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
if is_packed_cd != 0:
llvmlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1)
# 扫描字段类型,为跨模块结构体引用添加 opaque 声明
# 扫描字段类型:跨模块结构体引用在当前模块补声明
# 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque
for fi in range(field_count):
fty_addr_op: sizet = field_types_buf[fi]
if fty_addr_op == 0:
continue
fty_op: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr_op)
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
if self.Gen.ExprGenBase.is_ptr_type(fty_op) != 0:
# 指针字段:指向物只需 opaque 声明(GEP 不按字段下标解引用指向物本体)
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
else:
# 值类型字段(结构体本体 / 结构体数组):必须复制**完整定义**。只给
# opaque 会让**本类**变成 unsized(LLVM:含 unsized 成员的结构体自身
# unsized)⇒ 本模块内对本类做带字段下标的 GEP 时 llc 报
# "base element of getelementptr must be sized"。
# 现场:includes/condition.vp 的 Condition{cond_var: CONDITION_VARIABLE,
# cs: CRITICAL_SECTION}——后两者定义在 w32/win32sync.vp,且新近由
# `t.CTypedef = VOIDPTR` 改成 class(指针层级收紧后 c.Addr 需要一层指针)。
# _ensure_field_types_in_module 负责数组元素结构体的完整定义。
self.Gen.StructGen.ensure_struct_def_in_module(pool, trans.Module, fty_op)
self.Gen.StructGen._ensure_field_types_in_module(pool, trans.Module, fty_op)
# ============================================================
# 3. 注册到 HandlesStruct