From 96dad309ac9e5c76a90924e8b859d5ba09d53c83 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 15:58:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(classdef):=20=E5=80=BC=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E8=A1=A5=E5=AE=8C=E6=95=B4=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BD=93=E5=AE=9A=E4=B9=89=EF=BC=8C=E4=BF=AE=E5=A4=8D=E8=B7=A8?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=B5=8C=E5=A5=97=E7=BB=93=E6=9E=84=E4=BD=93?= =?UTF-8?q?=20unsized=20=E5=AF=BC=E8=87=B4=20llc=20GEP=20=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现场: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 覆盖数组元素。 --- App/lib/core/Gen/Class/ClassGenDef.vp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Class/ClassGenDef.vp b/App/lib/core/Gen/Class/ClassGenDef.vp index 1739d3d..dc97add 100644 --- a/App/lib/core/Gen/Class/ClassGenDef.vp +++ b/App/lib/core/Gen/Class/ClassGenDef.vp @@ -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