From a99db2a29b63e233a49090a72c86419d5c8c1d07 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 29 Aug 2026 10:28:39 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20REnum=20=E5=8F=98=E4=BD=93=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E4=BD=9C=E5=80=BC=E8=BF=94=E5=9B=9E=20tag=20=E5=B8=B8?= =?UTF-8?q?=E9=87=8F=20+=20kind()=20=E6=B3=A8=E8=A7=A3=E5=85=9C=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) 表达式中的 REnumClass.Variant 无括号引用(llvmlite.LLVMType.Struct)此前未处理 → 与 kind() 返回的 i32 tag 比较时条件翻译失败(TranslatorGenMixin L517 根因)。仿枚举成员访问,translate_attribute 增加变体引用 → tag 常量。2) kind() 特殊处理在运行时类型退化(联合 i8*)时无法识别 REnum 类,补变量注解类名兜底。 --- App/lib/core/Gen/Call/CallGenDispatch.vp | 100 +++++++++++++++-------- App/lib/core/Gen/Expr/ExprGenAttr.vp | 25 ++++++ 2 files changed, 91 insertions(+), 34 deletions(-) diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 99de6a7..8ad8d17 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -670,27 +670,27 @@ class CallGenDispatch(CallGenBase.CallGenBase): # ConstInt 的 name 参数是 IR 文本表示,ValuePrint 输出时使用 Name 而非 IntVal # 硬编码 "0" 会导致 IR 输出 i64 0 而非实际值 return llvmlite.const_int64(pool, sz_builtin) - sz_resolved_ty = None - # 模块限定类(w32.win32base.SECURITY_ATTRIBUTES):模块归属 - # 精确匹配定义侧结构体,防裸名全局匹配误命中跨模块同名类 - # (SECURITY_ATTRIBUTES 注册于 e710 但期望 a335 根因)。 - if sz_full_name is not None: - szf_dot: str = string.strrchr(sz_full_name, '.') - if szf_dot is not None: - szf_mod_len: t.CSizeT = t.CSizeT(t.CUInt64T(szf_dot) - t.CUInt64T(sz_full_name)) - szf_mod: str = pool.alloc(szf_mod_len + 1) - if szf_mod is not None: - string.strncpy(szf_mod, sz_full_name, szf_mod_len) - szf_mod[szf_mod_len] = '\0' - # t/c 内置库豁免(t.CInt 等已由内建/尺寸表处理) - if string.strcmp(szf_mod, "t") != 0 and string.strcmp(szf_mod, "c") != 0: - szf_sha1: str = self.Gen.StructGen._resolve_module_sha1( - szf_mod, trans._from_imports if trans is not None else None) - if szf_sha1 is not None: - szf_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(sz_cls_name, szf_sha1) - if szf_entry is not None and szf_entry.Ty is not None: - sz_resolved_ty = szf_entry.Ty - if sz_resolved_ty is None: + sz_resolved_ty = None + # 模块限定类(w32.win32base.SECURITY_ATTRIBUTES):模块归属 + # 精确匹配定义侧结构体,防裸名全局匹配误命中跨模块同名类 + # (SECURITY_ATTRIBUTES 注册于 e710 但期望 a335 根因)。 + if sz_full_name is not None: + szf_dot: str = string.strrchr(sz_full_name, '.') + if szf_dot is not None: + szf_mod_len: t.CSizeT = t.CSizeT(t.CUInt64T(szf_dot) - t.CUInt64T(sz_full_name)) + szf_mod: str = pool.alloc(szf_mod_len + 1) + if szf_mod is not None: + string.strncpy(szf_mod, sz_full_name, szf_mod_len) + szf_mod[szf_mod_len] = '\0' + # t/c 内置库豁免(t.CInt 等已由内建/尺寸表处理) + if string.strcmp(szf_mod, "t") != 0 and string.strcmp(szf_mod, "c") != 0: + szf_sha1: str = self.Gen.StructGen._resolve_module_sha1( + szf_mod, trans._from_imports if trans is not None else None) + if szf_sha1 is not None: + szf_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(sz_cls_name, szf_sha1) + if szf_entry is not None and szf_entry.Ty is not None: + sz_resolved_ty = szf_entry.Ty + if sz_resolved_ty is None: sz_resolved_ty = self.Gen.StructGen.get_struct_type(sz_cls_name) # 回退 1: 泛型类引用接收者 Stack[T].__sizeof__() — Subscript → 特化后计算大小 # (GenericTest2 Stack.type_size 依赖此路径) @@ -997,6 +997,7 @@ class CallGenDispatch(CallGenBase.CallGenBase): if rk_obj is not None and rk_obj.Ty is not None: rk_ty: llvmlite.LLVMType | t.CPtr = rk_obj.Ty rk_load: int = 0 + rk_cls: str = None if self.Gen.ExprGenBase.is_ptr_type(rk_ty) != 0: rk_pointee: llvmlite.LLVMType | t.CPtr = rk_ty.Pointee # 联合简化双指针(Ptr(Ptr(Struct)))→ 解一层 + load @@ -1004,20 +1005,51 @@ class CallGenDispatch(CallGenBase.CallGenBase): and self.Gen.ExprGenBase.is_ptr_type(rk_pointee) != 0: rk_pointee = rk_pointee.Pointee rk_load = 1 - rk_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, rk_pointee) + rk_cls = self.Gen.StructGen.get_class_name_by_type(pool, rk_pointee) if rk_cls is not None \ - and self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) != 0: - rk_val: llvmlite.Value | t.CPtr = rk_obj - if rk_load != 0: - rk_val = llvmlite.build_load(builder, rk_ty, rk_obj) - if rk_val is not None: - if hit_box is not None: - hit_box[0] = 1 - rk_i32p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( - pool, llvmlite.Int32(pool)) - rk_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, rk_val, rk_i32p) - return llvmlite.build_load(builder, rk_i32p, rk_cast) + and self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) == 0: + rk_cls = None + # 注解兜底:联合简化/退化后运行时类型丢失(如 + # resolved: llvmlite.LLVMType | t.CPtr 存 i8*,pointee 非 + # 结构体),用变量注解类名识别 REnum 类(kind() 语义: + # 读 __tag,bitcast 对象到 i32* + load)。 + if rk_cls is None and rk_at.value is not None \ + and rk_at.value.kind() == ast.ASTKind.Name and trans is not None: + rk_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rk_at.value) + if rk_nm.id is not None: + rk_ve: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry( + trans.SymTab, rk_nm.id) + if rk_ve is not None and rk_ve.AnnotClassName is not None: + rk_annot_raw: str = rk_ve.AnnotClassName + # 截断联合/泛型后缀(" | t.CPtr" / "[...]") + rk_ae: t.CSizeT = 0 + while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' \ + and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[': + rk_ae += 1 + rk_ab: str = pool.alloc(rk_ae + 1) + if rk_ab is not None: + string.strncpy(rk_ab, rk_annot_raw, rk_ae) + rk_ab[rk_ae] = '\0' + # 去模块前缀("llvmlite.LLVMType" → "LLVMType") + rk_ad: str = string.strrchr(rk_ab, '.') + if rk_ad is not None and rk_ad[1] != '\0': + rk_cls = rk_ad + 1 + else: + rk_cls = rk_ab + if self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) == 0: + rk_cls = None + if rk_cls is not None: + rk_val: llvmlite.Value | t.CPtr = rk_obj + if rk_load != 0: + rk_val = llvmlite.build_load(builder, rk_ty, rk_obj) + if rk_val is not None: + if hit_box is not None: + hit_box[0] = 1 + rk_i32p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( + pool, llvmlite.Int32(pool)) + rk_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + builder, rk_val, rk_i32p) + return llvmlite.build_load(builder, rk_i32p, rk_cast) # 检测类名静态/类方法调用: ClassName.method(args) # 当 cl.func 是 Attribute、value 是已注册结构体类名(非普通变量)时, # 且方法带 @staticmethod/@classmethod 元数据,走静态调用路径 diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index 7d0ec31..af3cbd9 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -479,6 +479,31 @@ class ExprGenAttr(ExprGenBase.ExprGenBase): f"(enum_members={dbg_mc})", "ATTR") return None + # REnum 变体引用作为值: ClassName.Variant / Module.ClassName.Variant → 变体 tag 常量 + # 如 llvmlite.LLVMType.Struct(if resolved.kind() == llvmlite.LLVMType.Struct 比较)。 + # 无括号引用(非构造调用)时变体名解析为该变体 tag(i32 常量),与 match 机制 + # _lookup_renum_variant_in_class 一致。工厂函数名(LLVMType.Int8 等非变体, + # 见 __types.vp)查变体返回 -1 → 自然落空不拦截。 + renum_cls_rv: str = None + if at.value.kind() == ast.ASTKind.Name: + rn_nm_rv: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if rn_nm_rv.id is not None: + renum_cls_rv = rn_nm_rv.id + elif at.value.kind() == ast.ASTKind.Attribute: + rn_at_rv: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(at.value) + if rn_at_rv.attr is not None: + renum_cls_rv = rn_at_rv.attr + if renum_cls_rv is not None \ + and self.Gen.ClassGenEnum._is_renum_class_name(renum_cls_rv) != 0: + rv_tag: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class( + renum_cls_rv, at.attr) + if rv_tag >= 0: + name_buf_rv: str = pool.alloc(32) + if name_buf_rv is not None: + viperlib.snprintf(name_buf_rv, 32, "%d", rv_tag) + return llvmlite.ConstInt(pool, llvmlite.Int32(pool), rv_tag, name_buf_rv) + return llvmlite.ConstInt(pool, llvmlite.Int32(pool), rv_tag, "0") + # FakeDuck: 影子结构体属性读取 (str 变量的 per-instance 字段) # a.__data__ / a.__mbuddy__ → GEP {a}__meta__[field] 并加载 # 对齐 TPC HandlesExprAttr.py L433-442:对象是 Name 变量且存在