From 1fe7878074e550c54c54bdd6eb1359ce037921bd Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 29 Aug 2026 17:27:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(compiler):=20=E5=AF=B9=E8=B1=A1=E7=B1=BB?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=BA=A7=E5=85=A8=E5=B1=80=E6=94=B9=E9=9D=99?= =?UTF-8?q?=E6=80=81=20BSS=20storage=EF=BC=8C=E4=BF=AE=E5=A4=8D=E9=A1=B5?= =?UTF-8?q?=200=20=E6=B7=B7=E5=8F=A0=E4=B8=8E=E6=A0=88=E6=82=AC=E5=9E=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对象类全局(裸类名注解)此前编译为 NULL 指针,实例建在栈 alloca 后悬垂,对象字段落在物理页 0(IVT+BDA 混叠),导致 VKernel devfs/fat32/sched 全部对象失效。新增 @g.stg 静态 storage(BSS),@g 编译期指向它;赋值/构造点(translate_assign/translate_annassign 全局分支)检测 storage 后绑定引用并复制对象,消除 NULL 与悬垂。 --- App/lib/core/Gen/AssignGenMixin.vp | 77 ++++++++++++++++++++++++++ App/lib/core/Gen/TranslatorGenMixin.vp | 48 +++++++++++++++- 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index ee462b9..6b98b2c 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -1165,6 +1165,30 @@ class AssignGenMixin: builder, pool, mod, aa.value, None, 0, trans) if rhs_val is not None: + # 对象类全局(有静态 storage):对象构造/赋值 → 绑定 storage + 复制对象 + stg_ref_aa: llvmlite.Value | t.CPtr = None + if nm.id is not None: + stg_key_aa: str = pool.alloc(t.CSizeT(string.strlen(nm.id)) + 8) + if stg_key_aa is not None: + viperlib.snprintf(stg_key_aa, t.CSizeT(string.strlen(nm.id)) + 8, "%s.__stg", nm.id) + stg_ref_aa = self.Gen.VarGen.lookup_module_var(trans.SymTab, stg_key_aa) + if stg_ref_aa is not None and rhs_val.Ty is not None \ + and stg_ref_aa.Ty is not None and stg_ref_aa.Ty.Pointee is not None: + stg_ty_aa: llvmlite.LLVMType | t.CPtr = stg_ref_aa.Ty.Pointee + rhs_inner_aa: llvmlite.LLVMType | t.CPtr = None + match rhs_val.Ty: + case llvmlite.LLVMType.Ptr(pointee_aa): + rhs_inner_aa = pointee_aa + case _: + pass + if rhs_inner_aa is not None and rhs_inner_aa.kind() == llvmlite.LLVMType.Struct \ + and stg_ty_aa == rhs_inner_aa: + llvmlite.build_store(builder, stg_ref_aa, mod_alloca) + stg_obj_val_aa: llvmlite.Value | t.CPtr = llvmlite.build_load( + builder, stg_ty_aa, rhs_val) + if stg_obj_val_aa is not None: + llvmlite.build_store(builder, stg_obj_val_aa, stg_ref_aa) + return 0 target_ty: llvmlite.LLVMType | t.CPtr = None if mod_alloca.Ty is not None: target_ty = mod_alloca.Ty.Pointee @@ -1218,6 +1242,30 @@ class AssignGenMixin: builder, pool, mod, aa.value, None, 0, trans) if rhs_val_mg is not None: + # 对象类全局(有静态 storage):对象构造/赋值 → 绑定 storage + 复制对象 + stg_ref_mg: llvmlite.Value | t.CPtr = None + if nm.id is not None: + stg_key_mg: str = pool.alloc(t.CSizeT(string.strlen(nm.id)) + 8) + if stg_key_mg is not None: + viperlib.snprintf(stg_key_mg, t.CSizeT(string.strlen(nm.id)) + 8, "%s.__stg", nm.id) + stg_ref_mg = self.Gen.VarGen.lookup_module_var(trans.SymTab, stg_key_mg) + if stg_ref_mg is not None and rhs_val_mg.Ty is not None \ + and stg_ref_mg.Ty is not None and stg_ref_mg.Ty.Pointee is not None: + stg_ty_mg: llvmlite.LLVMType | t.CPtr = stg_ref_mg.Ty.Pointee + rhs_inner_mg: llvmlite.LLVMType | t.CPtr = None + match rhs_val_mg.Ty: + case llvmlite.LLVMType.Ptr(pointee_mg): + rhs_inner_mg = pointee_mg + case _: + pass + if rhs_inner_mg is not None and rhs_inner_mg.kind() == llvmlite.LLVMType.Struct \ + and t.CUInt64T(stg_ty_mg) == t.CUInt64T(rhs_inner_mg): + llvmlite.build_store(builder, stg_ref_mg, mod_glob) + stg_obj_val_mg: llvmlite.Value | t.CPtr = llvmlite.build_load( + builder, stg_ty_mg, rhs_val_mg) + if stg_obj_val_mg is not None: + llvmlite.build_store(builder, stg_obj_val_mg, stg_ref_mg) + return 0 target_ty_mg: llvmlite.LLVMType | t.CPtr = None if mod_glob.Ty is not None: target_ty_mg = mod_glob.Ty.Pointee @@ -1826,6 +1874,35 @@ class AssignGenMixin: target, f"global 变量 '{nm.id}' 未注册,无法赋值", "NameError") + # 对象类全局(裸类名注解 → 静态 storage):对象构造/赋值 → 引用 + # 绑定到 storage + 复制对象到 storage。否则 store 栈 alloca 指针 + # 悬垂(devfs serial0_file 根因),或模块级构造初始化器被丢弃后 + # 全局保持 NULL(页 0 混叠根因,见 TranslatorGenMixin storage 逻辑)。 + stg_ref_as: llvmlite.Value | t.CPtr = None + if nm.id is not None: + stg_key_as: str = pool.alloc(t.CSizeT(string.strlen(nm.id)) + 8) + if stg_key_as is not None: + viperlib.snprintf(stg_key_as, t.CSizeT(string.strlen(nm.id)) + 8, "%s.__stg", nm.id) + stg_ref_as = self.Gen.VarGen.lookup_module_var(trans.SymTab, stg_key_as) + if stg_ref_as is not None and rhs_val is not None and rhs_val.Ty is not None \ + and stg_ref_as.Ty is not None and stg_ref_as.Ty.Pointee is not None: + stg_ty_as: llvmlite.LLVMType | t.CPtr = stg_ref_as.Ty.Pointee + rhs_inner_as: llvmlite.LLVMType | t.CPtr = None + match rhs_val.Ty: + case llvmlite.LLVMType.Ptr(pointee_as): + rhs_inner_as = pointee_as + case _: + pass + if rhs_inner_as is not None and rhs_inner_as.kind() == llvmlite.LLVMType.Struct \ + and t.CUInt64T(stg_ty_as) == t.CUInt64T(rhs_inner_as): + # 1) @g 引用绑定到 storage(丢弃临时 alloca,避免悬垂) + llvmlite.build_store(builder, stg_ref_as, mod_alloca) + # 2) 复制构造结果(临时对象)到 storage(函数内复制,alloca 仍有效) + stg_obj_val_as: llvmlite.Value | t.CPtr = llvmlite.build_load( + builder, stg_ty_as, rhs_val) + if stg_obj_val_as is not None: + llvmlite.build_store(builder, stg_obj_val_as, stg_ref_as) + continue target_ty: llvmlite.LLVMType | t.CPtr = None if mod_alloca.Ty is not None: target_ty = mod_alloca.Ty.Pointee diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 113272c..54db717 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -488,6 +488,7 @@ class TranslatorGenMixin: var_name: str = None var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + resolved_stg_ty: llvmlite.LLVMType | t.CPtr = None # 对象类全局:静态 storage 类型(BSS 实例) init_val: t.CInt64T = 0 init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str init_str_val: str = None @@ -518,6 +519,11 @@ class TranslatorGenMixin: gv_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(resolved) if gv_entry is not None \ and (gv_entry.HasNew != 0 or gv_entry.HasVTable != 0 or gv_entry.IsOOP != 0): + # 对象类全局(裸类名注解 → 对象即指针):记录原 Struct 值类型, + # 用于创建静态 storage 全局承载对象实例(BSS)。 + # 否则 @g = global T* zeroinitializer → NULL → 对象字段落在 + # 物理页 0(IVT+BDA 混叠),devfs/fat32/sched 全部对象失效根因。 + resolved_stg_ty = resolved resolved = llvmlite.Ptr(pool, resolved) var_ty = resolved # 解析初始值(支持整数、列表字面量、字符串字面量) @@ -650,7 +656,47 @@ class TranslatorGenMixin: else: # 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer, # 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type" - gv.Initializer = "zeroinitializer" + # 对象类全局(有 storage)的 Initializer 由下方 storage 逻辑设为 &@storage, + # 此处不覆盖。 + if resolved_stg_ty is None: + gv.Initializer = "zeroinitializer" + + # 对象类全局:创建静态 storage 全局(BSS)承载对象实例,@g 编译期引用它。 + # 函数内 `g = T()` 构造时把对象复制到 storage(见 AssignGenMixin 全局分支), + # 不再依赖栈 alloca(悬垂);c.Addr(g) load @g 得到 &storage,均非 NULL。 + if resolved_stg_ty is not None: + # 值类型 storage 需要完整 struct 定义(跨模块类默认 opaque → + # @g.stg = global %T zeroinitializer 报 "use of undefined type") + self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved_stg_ty) + stg_name_len: t.CSizeT = t.CSizeT(string.strlen(mangled_name)) + 8 + stg_name_buf: str = pool.alloc(stg_name_len) + if stg_name_buf is not None: + viperlib.snprintf(stg_name_buf, stg_name_len, "%s.stg", mangled_name) + stg_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable( + pool, stg_name_buf, resolved_stg_ty) + if stg_gv is not None: + llvmlite.module_add_global(mod, stg_gv) + stg_gv.Linkage = None + stg_gv.Initializer = "zeroinitializer" + # @g 初始值 = &@storage(对象引用指向 BSS 实例,非 NULL) + stg_init_len: t.CSizeT = t.CSizeT(string.strlen(mangled_name)) + 8 + stg_init_buf: str = pool.alloc(stg_init_len) + if stg_init_buf is not None: + if self.Gen.ClassGenVTable._vtable_name_needs_quote(stg_name_buf) != 0: + viperlib.snprintf(stg_init_buf, stg_init_len, "@\"%s\"", stg_name_buf) + else: + viperlib.snprintf(stg_init_buf, stg_init_len, "@%s", stg_name_buf) + gv.Initializer = stg_init_buf + # 注册 storage 引用(key: var_name.__stg),供 AssignGenMixin + # 全局赋值分支检测对象类全局并复制对象到 storage。 + stg_ref: llvmlite.Value | t.CPtr = self.Gen.ExprGenAttr.make_global_ref( + pool, stg_name_buf, resolved_stg_ty) + if stg_ref is not None: + stg_key_len: t.CSizeT = t.CSizeT(string.strlen(var_name)) + 8 + stg_key: str = pool.alloc(stg_key_len) + if stg_key is not None: + viperlib.snprintf(stg_key, stg_key_len, "%s.__stg", var_name) + self.Gen.VarGen.define_module_var(trans.SymTab, stg_key, stg_ref) # 创建 Value 引用(@mangled_name, 类型为 var_ty*) var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)