fix(tpv): REnum 变体引用作值返回 tag 常量 + kind() 注解兜底
1) 表达式中的 REnumClass.Variant 无括号引用(llvmlite.LLVMType.Struct)此前未处理 → 与 kind() 返回的 i32 tag 比较时条件翻译失败(TranslatorGenMixin L517 根因)。仿枚举成员访问,translate_attribute 增加变体引用 → tag 常量。2) kind() 特殊处理在运行时类型退化(联合 i8*)时无法识别 REnum 类,补变量注解类名兜底。
This commit is contained in:
1 parent
58d61badcb
commit
a99db2a29b
2 files changed
+91
-34
No files matched your search
@@ -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 元数据,走静态调用路径
|
||||
|
||||
@@ -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 变量且存在
|
||||
|
||||
Reference in new issue
Block a user