- Phase2 PhaseA-DBG 探针:精确匹配失败后后缀匹配(别名=基名如 GenTypes→lib.core.Gen.GenTypes),t/c 内置模块跳过,改名别名标'未解析'而非'缺失',消息头改'依赖探测明细' - ClassGenDef 两个 _deps_pending 置位点加 [PHASEADBG] 打印(父类未注册 class/parent、字段注解未解析 class/field/annot_kind) - MatchGenMixin _handle_renum_match 加 [MATCHDBG] 打印(renum 元信息 + 第一/二遍 case 列表快照对比,定位 REnum match 崩溃的列表破坏点)
579 lines
34 KiB
Plaintext
579 lines
34 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import stdlib
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.Stub.StubMerger as StubMerger
|
||
import lib.core.CompilerFactory as CompilerFactory
|
||
|
||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||
|
||
|
||
# ============================================================
|
||
# ClassGenDef - ClassGenMixin 拆分(阶段 D):translate_class_def 主入口
|
||
#
|
||
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class ClassGenDef(ClassGenBase.ClassGenBase):
|
||
"""translate_class_def 主入口"""
|
||
|
||
# ============================================================
|
||
# translate_class_def — 翻译 class 定义(簇 D)
|
||
# ============================================================
|
||
def translate_class_def(self, trans: HT.Translator | t.CPtr,
|
||
node: ast.AST | t.CPtr) -> int:
|
||
"""翻译 class 定义,返回 0"""
|
||
if node is None or trans is None:
|
||
return 0
|
||
|
||
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node)
|
||
if cd is None or cd.name is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
class_name: str = cd.name
|
||
|
||
if trans.ModuleSha1 is None:
|
||
# fail-fast:翻译类时模块 SHA1 缺失(命名空间隔离依赖它)——
|
||
VLogger.error("翻译类时 ModuleSha1 缺失", "CLASS")
|
||
self.Gen.TypeGenErr.fatal_error(cd, "翻译类时 ModuleSha1 缺失", "TypeError")
|
||
|
||
# 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前,
|
||
# 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类)
|
||
self.Gen.StructGen.add_visible_struct(pool, class_name)
|
||
|
||
# 枚举类:交给 HandlesEnum 处理
|
||
if self.Gen.ClassGenBase._is_enum_class(cd, trans) == 1:
|
||
return self.Gen.ClassGenEnum._translate_enum_def(trans, cd)
|
||
|
||
# 联合体类:交给联合体处理
|
||
if self.Gen.ClassGenBase._is_union_class(cd, trans) == 1:
|
||
return self.Gen.ClassGenEnum._translate_union_def(trans, cd)
|
||
|
||
# REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局)
|
||
if self.Gen.ClassGenBase._is_renum_class(cd, trans) == 1:
|
||
return self.Gen.ClassGenEnum._translate_renum_def(trans, cd)
|
||
|
||
# 泛型类:存储为模板,不发射 IR(等实例化时特化)
|
||
# 用局部变量接收 cd.type_params,触发类型推断
|
||
tp_val: list[str] | t.CPtr = cd.type_params
|
||
if self.Gen.ClassGenGeneric._is_generic_class(tp_val) == 1:
|
||
self.Gen.ClassGenGeneric._register_generic_template(pool, cd, trans.ModuleSha1)
|
||
return 0
|
||
|
||
# 异常类(try-except):注册编码+继承树,不生成 struct
|
||
# (对齐 TPC HandlesClassDef.py L509-511:_is_exception_class →
|
||
# _RegisterExceptionClass → return,异常类不编译为结构体)
|
||
if self.Gen.ClassGenBase._is_exception_class_def(cd) == 1:
|
||
return self.Gen.ClassGenBase._register_exception_class_def(trans, cd)
|
||
|
||
# 检查是否已注册(用 SHA1 区分跨模块同名类)
|
||
existing: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
if existing is not None:
|
||
# BUG 5 方案1修改点2:existing 时字段完整性检查
|
||
# 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整)
|
||
# 注意:无字段类(接口/标记类,类体无 AnnAssign)合法(空 struct + 方法),
|
||
# 仅当"类体声明了字段但 FieldCount==0"才算注册不完整(Phase A-pre 漏注册)。
|
||
if existing.FieldCount == 0 and trans._declare_only == 0:
|
||
if self.Gen.ClassGenBase._class_body_has_field(cd) != 0:
|
||
# Phase B 时字段数为 0 说明注册不完整(Phase A-pre 可能漏注册)
|
||
self.Gen.TypeGenErr.fatal_error(
|
||
node,
|
||
f"结构体已注册但字段数为0,类: {class_name},可能注册不完整",
|
||
"InternalCompilerError")
|
||
# 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法
|
||
if existing.Ty is not None:
|
||
# Phase 1b(declare_only=0):existing.Ty 是 Phase 1a 注册的 struct_ty,
|
||
# 其 Name(如 "sha1.ClassName")指向 Phase 1a 的 pool 内存。虽然 mark1
|
||
# 之前分配不被 reset 回收,但 struct_ty 会被后续文件翻译引用(vtable/
|
||
# self 参数类型打印),部分实现下 pool 块被复用导致 Name 悬空崩溃。
|
||
# 保险起见:深拷贝 Name 到 stdlib,确保跨文件永久存活。
|
||
if trans._declare_only == 0:
|
||
# 深拷贝整个 existing.Ty 到 stdlib:1a pool Ty 跨 1b reset 悬空,
|
||
# _ensure_field_types_in_module 遍历悬空字段 ParamNode 链表
|
||
# 读悬空挂起(G3 LinkedNode.prepend 挂起根因)。DeepCopyType
|
||
# 递归深拷贝字段链表/子类型/Name 到 stdlib(深度上限+链守卫)。
|
||
ty_deep: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(
|
||
CompilerFactory.get_perm_pool(), existing.Ty)
|
||
if ty_deep is not None:
|
||
existing.Ty = ty_deep
|
||
old_name: str = llvmlite.get_struct_name(existing.Ty)
|
||
if old_name is not None:
|
||
on_len: t.CSizeT = string.strlen(old_name)
|
||
on_copy: str = CompilerFactory.get_perm_pool().alloc(on_len + 1)
|
||
if on_copy is not None:
|
||
string.strcpy(on_copy, old_name)
|
||
c.DerefAs(existing.Ty, llvmlite.LLVMType.Struct(
|
||
llvmlite.get_struct_fields(existing.Ty),
|
||
llvmlite.get_struct_fcount(existing.Ty),
|
||
on_copy))
|
||
# Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行)
|
||
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
|
||
# Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体
|
||
# Phase B(declare_only=0)时全量翻译方法体
|
||
if trans._declare_only == 1:
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name, 1)
|
||
else:
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name)
|
||
# SHA1 已在 register_struct 时设置,无需再补
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])
|
||
# 必须在 _detect_vtable_status 和父类字段继承之前调用,
|
||
# 否则 find_struct_by_module("GSListNode[Value]") 返回 None
|
||
# ============================================================
|
||
self.Gen.ClassGenBase._trigger_base_specialization(trans, cd)
|
||
|
||
# ============================================================
|
||
# VTable 检测:判断是否启用虚表
|
||
# ============================================================
|
||
has_vtable: int = self.Gen.ClassGenBase._detect_vtable_status(cd, trans)
|
||
parent_name: str = self.Gen.ClassGenBase._get_parent_class(cd, trans)
|
||
# 多继承:收集所有真实父类名(跳过 marker base),供字段展平/vtable/MRO 使用
|
||
parents_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.PARENT_MAX)
|
||
parents_count: int = 0
|
||
if parents_buf is not None:
|
||
parents_count = self.Gen.ClassGenBase._collect_parents(pool, cd, parents_buf, GenTypes.PARENT_MAX, trans)
|
||
is_novtable_deco: int = 0
|
||
if cd.decorator_list is not None:
|
||
if self.Gen.ClassGenBase._has_decorator(cd.decorator_list, "NoVTable") == 1:
|
||
is_novtable_deco = 1
|
||
|
||
# ============================================================
|
||
# PhaseA 预注册延迟检查:父类未注册时延迟注册当前类
|
||
#
|
||
# 根因:AssignHandle(HandlesBase.Mixin) 有自己的字段 _CurrentClass,
|
||
# 当 Mixin 未注册时(字母序:HandlesAssign.py 在 HandlesBase.py 之前),
|
||
# field_count=1(不是0),field_count==0 静默返回不触发,
|
||
# AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans)。
|
||
# 后续遍 existing is not None,不补字段 → attribute ptr is None: self.Trans
|
||
#
|
||
# 修复:declare_only==1 且父类未注册时,延迟注册到下一遍。
|
||
# 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。
|
||
# Phase B(declare_only==0)不延迟,避免死锁。
|
||
# ============================================================
|
||
if trans._declare_only == 1 and parent_name is not None:
|
||
parent_check: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if parent_check is None:
|
||
parent_check = self.Gen.StructGen.find_struct(parent_name)
|
||
if parent_check is None:
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 1. 遍历 class body,收集字段信息
|
||
# ============================================================
|
||
# 用 CSizeT 数组存储指针值(64 位系统上 8 字节)
|
||
field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
if field_names_buf is None or field_types_buf is None or field_defaults_buf is None:
|
||
return 0
|
||
if field_annot_buf is None:
|
||
return 0
|
||
string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_defaults_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_annot_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
|
||
field_count: int = 0
|
||
|
||
# ============================================================
|
||
# 1.5 继承父类字段(字段展平)
|
||
# ============================================================
|
||
#
|
||
# 父类字段排在子类字段之前,结构体布局:
|
||
# [vtable_ptr?, parent_field1, ..., child_field1, ...]
|
||
# 跳过父类的 __vtable__ 字段(子类会有自己的 vtable 指针)
|
||
# ============================================================
|
||
# 多继承字段展平:遍历所有父类(声明顺序),字段名去重(先声明优先)
|
||
if parents_count > 0 and parents_buf is not None:
|
||
for pi in range(parents_count):
|
||
pname_addr: t.CSizeT = parents_buf[pi]
|
||
if pname_addr == 0:
|
||
continue
|
||
pname: str = (str | t.CPtr)(t.CVoid(pname_addr, t.CPtr))
|
||
if pname is None:
|
||
continue
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
parent_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(
|
||
pname, trans.ModuleSha1)
|
||
if parent_entry is None:
|
||
# 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin),
|
||
# find_struct_by_module 不回退全局查找,此处手动回退到 find_struct,
|
||
# 否则子类无法继承父类字段 → field_count==0 → __sizeof__ 失败
|
||
parent_entry = self.Gen.StructGen.find_struct(pname)
|
||
if parent_entry is None:
|
||
# 父类尚未注册(依赖模块未翻译:Phase A 按文件序,子类模块可能
|
||
# 先于父类模块,如 Generator.vp G < TypeGenMixin.vp T)。此时
|
||
# **不能**继续注册——StructTable 在 StdlibAlloc=1 时用 perm_pool
|
||
# 分配(init_struct_table L136-140),残缺条目跨 pass 存活,
|
||
# 后续 pass 的 existing 早退(L2995-3006)永远无法修复 → 子类
|
||
# __init__ 写父类字段(self.TraceFrames)每遍永久失败。
|
||
# 整类 defer(不注册)+ 标记 _deps_pending 下遍重译;模块级
|
||
# 变量/函数参数解析失败静默降级 i32(handle_module_level_var
|
||
# L422-426 / FuncGenMixin L482-483),不致命,本遍文件不写盘。
|
||
if trans is not None:
|
||
trans._deps_pending = 1
|
||
# [PHASEADBG] 临时诊断:父类未注册即 pending 的根因(用后移除)
|
||
stdio.printf("[PHASEADBG] 父类未注册: class=%s parent=%s\n", class_name, pname)
|
||
return 0
|
||
pfc: int = parent_entry.FieldCount
|
||
for pfi in range(pfc):
|
||
pfe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
|
||
parent_entry, pfi)
|
||
if pfe is None:
|
||
continue
|
||
pfn: str = self.Gen.StructGen.get_field_name_ptr(pfe)
|
||
if pfn is None:
|
||
continue
|
||
# 跳过父类的 vtable 指针字段
|
||
if string.strcmp(pfn, "__vtable__") == 0:
|
||
continue
|
||
# 多继承去重:字段名已存在跳过(先声明父类优先)
|
||
if self.Gen.ClassGenBase._field_name_exists(field_names_buf, field_count, pfn) != 0:
|
||
continue
|
||
if field_count < GenTypes.FIELD_MAX:
|
||
pft: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_field_type_ptr(pfe)
|
||
pfd: ast.AST | t.CPtr = self.Gen.StructGen.get_field_default_ptr(pfe)
|
||
pfa: str = self.Gen.StructGen.get_field_annot_class_name(pfe)
|
||
field_names_buf[field_count] = t.CSizeT(pfn)
|
||
field_types_buf[field_count] = t.CSizeT(pft)
|
||
if pfd is not None:
|
||
field_defaults_buf[field_count] = t.CSizeT(pfd)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
if pfa is not None:
|
||
stored_val: t.CSizeT = t.CSizeT(pfa)
|
||
field_annot_buf[field_count] = stored_val
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
field_count += 1
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return 0
|
||
|
||
cn: t.CSizeT = len(children)
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
sk: int = stmt.kind()
|
||
|
||
if sk != ast.ASTKind.AnnAssign: continue
|
||
|
||
# AnnAssign(target=Name(id), annotation=type, value=...)
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
|
||
if aa is None or aa.target is None:
|
||
continue
|
||
|
||
# 获取字段名
|
||
if aa.target.kind() != ast.ASTKind.Name:
|
||
continue
|
||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||
if tgt.id is None:
|
||
continue
|
||
|
||
# 类体 CDefine 常量(任意位置,2026-08-10):注册到全局 CDefine 表。
|
||
# 方法内裸名(如 ISINSTANCE_CLASS_MAX)经 translate_name_value 查
|
||
# CDefine 表解析为常量值;类体开头的常量(MRO_MAX 等)由早期预注册
|
||
# 路径注册,但方法之后的 AnnAssign 不经过那些路径 → 此处统一兜底注册。
|
||
if self.Gen.AssignGen.is_cdefine_annotation(aa.annotation) != 0:
|
||
if aa.value is not None:
|
||
self.Gen.AssignGen._register_cdefine_from_value(pool, tgt.id, aa.value)
|
||
# CDefine 字段类型固定 i32,直接收集后跳过通用注解解析:
|
||
# resolve_annotation_type 不识别 "CDefine"(map_t_type/CTypedef
|
||
# 表均无此名),类体尾部常量(ISINSTANCE_CLASS_MAX 是首个触发
|
||
# 该路径的实例)Phase B 会 NameError: 't.CDefine' is not defined。
|
||
# 与类头常量(MRO_MAX 等)的 i32 字段语义保持一致。
|
||
if field_count < GenTypes.FIELD_MAX:
|
||
cdef_ty_l: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
if cdef_ty_l is not None:
|
||
field_names_buf[field_count] = t.CSizeT(tgt.id)
|
||
field_types_buf[field_count] = t.CSizeT(cdef_ty_l)
|
||
if aa.value is not None:
|
||
field_defaults_buf[field_count] = t.CSizeT(aa.value)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
field_count += 1
|
||
continue
|
||
|
||
# 跳过编译期元数据字段(__provides__/__requires__/__require_must__)
|
||
# 这些字段只用于 with 上下文的静态可达性检查,不生成运行时代码
|
||
# (FakeDuck:_str.__requires__=['__mbuddy__'])。此处解析 list[str]
|
||
# 字面量注册到持久元数据表,供 requires 注入 / with provider 查询。
|
||
if string.strcmp(tgt.id, "__provides__") == 0:
|
||
self.Gen.ClassGenBase._register_class_meta_list(pool, GenTypes.CLASS_META_PROVIDES, class_name, aa.value)
|
||
continue
|
||
if string.strcmp(tgt.id, "__requires__") == 0:
|
||
self.Gen.ClassGenBase._register_class_meta_list(pool, GenTypes.CLASS_META_REQUIRES, class_name, aa.value)
|
||
continue
|
||
if string.strcmp(tgt.id, "__require_must__") == 0:
|
||
self.Gen.ClassGenBase._register_class_meta_list(pool, GenTypes.CLASS_META_REQUIRE_MUST, class_name, aa.value)
|
||
continue
|
||
|
||
# 解析字段类型
|
||
field_ty: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||
# 单参 t.CArray[elem] + 列表字面量 → 静态数组 [N x elem]
|
||
# (与局部 AnnAssign 路径一致,对齐 TPC ParseListAnnotation 语义):
|
||
# 否则字段保持 Ptr(elem)(如 t.CArray[str] → i8**),
|
||
# for x in self.field 会误走指针迭代(元素非整数 → null 终止符
|
||
# 检查失败报错)。推断为静态数组后走数组迭代(按长度 N)。
|
||
if field_ty is not None:
|
||
field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(
|
||
pool, aa.annotation, aa.value, field_ty)
|
||
if field_ty is None:
|
||
# BUG 5 方案1修改点1:消除 i32 静默回退
|
||
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍
|
||
# Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止该类翻译
|
||
# 不再用 i32 回退(会导致结构体布局错误 + GEP 索引错乱)
|
||
# 例外:泛型 Subscript(如 list[AST|t.CPtr])未特化时回退为 Ptr(i8),
|
||
# 因为泛型特化可能延迟到构造调用时。AnnotClassName 会携带 mangled name
|
||
# 供 translate_attribute 做后续 bitcast。
|
||
is_generic_sub: int = 0
|
||
if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Subscript:
|
||
is_generic_sub = 1
|
||
if is_generic_sub != 0:
|
||
# 泛型未特化:回退为 Ptr(i8),依赖 AnnotClassName 做后续类型恢复
|
||
field_ty = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
else:
|
||
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,
|
||
# 静默 return 0 让多遍收敛机制生效(下一遍依赖类已注册即可成功)
|
||
if trans._declare_only == 1:
|
||
return 0
|
||
# Phase A(declare_only=0,Phase2.vp L573 多遍):依赖模块按
|
||
# 文件序可能晚于本模块翻译(如 TypeGenMixin.vp G < HandlesType.vp
|
||
# H,TraceFrames 注解的 HandlesType.TraceFrame 未注册)→ 标记
|
||
# _deps_pending 下遍重译,不在本遍以残缺字段注册结构体。
|
||
# 真正的类型错误由 Phase A 收敛检查暴露("Phase A 无法完成
|
||
# 翻译: <file>,请检查依赖模块是否已编译/注册"),不静默掩盖。
|
||
if trans is not None:
|
||
trans._deps_pending = 1
|
||
# [PHASEADBG] 临时诊断:字段注解类型未解析即 pending 的根因(用后移除)
|
||
dbg_ak: t.CInt = -1
|
||
if aa.annotation is not None:
|
||
dbg_ak = aa.annotation.kind()
|
||
stdio.printf("[PHASEADBG] 字段类型未解析: class=%s field=%s annot_kind=%d\n",
|
||
class_name, tgt.id, dbg_ak)
|
||
return 0
|
||
# 旧行为:fast-fail NameError(已移除——Phase A 依赖未就绪时
|
||
# 误报真实错误,中断多遍收敛;真实错误交给收敛检查兜底)
|
||
|
||
# 存储到数组(指针转 CSizeT)
|
||
if field_count < GenTypes.FIELD_MAX:
|
||
diag_name_val: t.CSizeT = t.CSizeT(tgt.id)
|
||
field_names_buf[field_count] = diag_name_val
|
||
field_types_buf[field_count] = t.CSizeT(field_ty)
|
||
# 存储默认值 AST 指针(None=无默认值)
|
||
if aa.value is not None:
|
||
field_defaults_buf[field_count] = t.CSizeT(aa.value)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
# 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体)
|
||
# BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST|t.CPtr]")
|
||
if aa.annotation is not None:
|
||
annot_cn: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
|
||
aa.annotation, trans._imported_modules, pool, trans._from_imports)
|
||
if annot_cn is not None:
|
||
diag_cn_val: t.CSizeT = t.CSizeT(annot_cn)
|
||
field_annot_buf[field_count] = diag_cn_val
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
field_count += 1
|
||
|
||
if field_count == 0:
|
||
# PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描),
|
||
# 导致子类无法继承父类字段 → field_count==0。
|
||
# 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。
|
||
if trans._declare_only == 1 and parent_name is not None:
|
||
return 0
|
||
# 无字段类(接口/标记类):不能整体跳过——类可能只有方法
|
||
# (如多继承中的 ShapeM/Vec2Extra),需注册类并翻译方法。
|
||
# 空 struct 在 LLVM 中合法({});@t.CVTable 类由下方补 vtable 指针字段。
|
||
|
||
# ============================================================
|
||
# 2. 创建 LLVM StructType
|
||
# ============================================================
|
||
# 构建 ParamNode 链表
|
||
first_node: llvmlite.ParamNode | t.CPtr = None
|
||
prev_node: llvmlite.ParamNode | t.CPtr = None
|
||
total_field_count: int = field_count
|
||
|
||
# 如果有虚表,首字段添加 i8* vtable 指针
|
||
if has_vtable == 1:
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if vtable_node is None:
|
||
fb_vn: str = VLogger.fmt_buf()
|
||
if fb_vn is not None:
|
||
viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name)
|
||
VLogger.error(fb_vn, "CLASS")
|
||
return 0
|
||
string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__())
|
||
vtable_node.Ty = i8_ptr_ty
|
||
first_node = vtable_node
|
||
prev_node = vtable_node
|
||
total_field_count = field_count + 1
|
||
|
||
for fi in range(field_count):
|
||
fty_addr: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr == 0:
|
||
continue
|
||
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr))
|
||
|
||
# 创建 ParamNode
|
||
pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if pnode is None:
|
||
continue
|
||
string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
|
||
pnode.Ty = fty
|
||
|
||
if first_node is None:
|
||
first_node = pnode
|
||
if prev_node is not None:
|
||
prev_node.Next = pnode
|
||
prev_node = pnode
|
||
|
||
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
|
||
# 注意: Phase 1b(declare_only=0)时 struct_ty 会注册到全局表并被后续
|
||
# 文件翻译引用(vtable/self 参数类型打印),其 Name 必须跨 1b 每文件
|
||
# reset_to(mark1) 存活 → 用 stdlib 深拷贝;Phase 1a 仍用 pool(无需跨文件)。
|
||
type_name: str = class_name
|
||
if trans.ModuleSha1 is not None:
|
||
name_buf: str = pool.alloc(64)
|
||
if name_buf is not None:
|
||
viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
|
||
type_name = name_buf
|
||
if trans._declare_only == 0 and type_name is not None:
|
||
tn_len: t.CSizeT = string.strlen(type_name)
|
||
tn_copy: str = CompilerFactory.get_perm_pool().alloc(tn_len + 1)
|
||
if tn_copy is not None:
|
||
string.strcpy(tn_copy, type_name)
|
||
type_name = tn_copy
|
||
|
||
# 创建 StructType(命名结构体)
|
||
struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name)
|
||
if struct_ty is None:
|
||
fb_st: str = VLogger.fmt_buf()
|
||
if fb_st is not None:
|
||
viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name)
|
||
VLogger.error(fb_st, "CLASS")
|
||
return 0
|
||
|
||
# Phase 1b(declare_only=0)新注册的 struct_ty 会被注册到全局表并被后续文件
|
||
# 翻译引用(vtable/self 参数类型打印/find_struct_by_type 指针匹配)。LLVMType
|
||
# 对象和 Fields 链是 pool 分配的,本文件 reset_to(mark1) 后悬空。深拷贝整棵树
|
||
# 到 stdlib,并替换 struct_ty 指针,保证 entry.Ty 与调用方持有的 struct_ty
|
||
# 指向同一个 stdlib 拷贝(指针匹配不失效)且跨文件永久存活。
|
||
# StdlibAlloc=1(Phase2 mark2 后)也必须深拷贝:Phase A-pre-inc(declare_only=1)
|
||
# 预注册 includes 时若仍用 pool struct_ty,reset_to(mark2) 后 entry.Ty 悬空 →
|
||
# 后续文件字段类型引用(resolve → Ptr(entry.Ty))→ opaque 扫描遍历悬空 fields
|
||
# 崩溃(LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。
|
||
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
|
||
st_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(
|
||
CompilerFactory.get_perm_pool(), struct_ty)
|
||
if st_copy is not None:
|
||
struct_ty = st_copy
|
||
type_name = llvmlite.get_struct_name(struct_ty)
|
||
|
||
# 注册命名结构体到模块(输出 %"name" = type { ... } 定义行)
|
||
llvmlite.module_add_named_type(trans.Module, pool, struct_ty)
|
||
|
||
# 扫描字段类型,为跨模块结构体引用添加 opaque 声明
|
||
# 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque
|
||
for fi in range(field_count):
|
||
fty_addr_op: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr_op == 0:
|
||
continue
|
||
fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr))
|
||
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
|
||
|
||
# ============================================================
|
||
# 3. 注册到 HandlesStruct
|
||
# ============================================================
|
||
entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.register_struct(
|
||
pool, class_name, struct_ty, trans.ModuleSha1)
|
||
if entry is None:
|
||
fb_re: str = VLogger.fmt_buf()
|
||
if fb_re is not None:
|
||
viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name)
|
||
VLogger.error(fb_re, "CLASS")
|
||
return 0
|
||
|
||
# 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错)
|
||
if has_vtable == 1:
|
||
entry.HasVTable = 1
|
||
if is_novtable_deco == 1:
|
||
entry.IsNoVTable = 1
|
||
if parent_name is not None:
|
||
# 1b 阶段父类名是 pool 字符串(本文件 AST/1a 预存),reset 后悬空;
|
||
# _translate_oop_methods/_detect_vtable_status 会在后续文件
|
||
# find_struct(ParentName) strcmp 解引用 → 用 stdlib 拷贝保证跨文件存活
|
||
if self.Gen.StructGen.get_stdlib_alloc() != 0:
|
||
pn_len: t.CSizeT = string.strlen(parent_name)
|
||
pn_buf: str = CompilerFactory.get_perm_pool().alloc(pn_len + 1)
|
||
if pn_buf is not None:
|
||
string.strcpy(pn_buf, parent_name)
|
||
entry.ParentName = pn_buf
|
||
else:
|
||
entry.ParentName = parent_name
|
||
# 多继承:设置父类数组(供 MRO/字段/vtable 查询,stdlib 深拷贝跨文件存活)
|
||
if parents_count > 0 and parents_buf is not None:
|
||
self.Gen.StructGen.set_parent_names(pool, class_name, parents_buf, parents_count)
|
||
|
||
# 添加字段信息
|
||
# 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始
|
||
if has_vtable == 1:
|
||
i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
self.Gen.StructGen.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None)
|
||
|
||
for fi in range(field_count):
|
||
fname_addr: t.CSizeT = field_names_buf[fi]
|
||
if fname_addr == 0:
|
||
continue
|
||
fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
|
||
fty_addr2: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr2 == 0:
|
||
continue
|
||
fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr))
|
||
# 恢复默认值 AST 指针
|
||
fdef_addr: t.CSizeT = field_defaults_buf[fi]
|
||
fdef: ast.AST | t.CPtr = None
|
||
if fdef_addr != 0:
|
||
fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr))
|
||
# 恢复注解类名指针
|
||
fannot_addr: t.CSizeT = field_annot_buf[fi]
|
||
fannot: str = None
|
||
if fannot_addr != 0:
|
||
fannot = (str)(t.CVoid(fannot_addr, t.CPtr))
|
||
if fname is not None and fty2 is not None:
|
||
self.Gen.StructGen.add_field(pool, entry, fname, fty2, fdef, fannot)
|
||
|
||
# Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体
|
||
if trans._declare_only == 1:
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, struct_ty, class_name, 1)
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__
|
||
# ============================================================
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, struct_ty, class_name)
|
||
|
||
return 0 |