diff --git a/App/lib/core/BuildPipeline.vp b/App/lib/core/BuildPipeline.vp index f141310..0b29186 100644 --- a/App/lib/core/BuildPipeline.vp +++ b/App/lib/core/BuildPipeline.vp @@ -142,9 +142,10 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, gen.__before_init__() gen.__init__(mb) GenGenerator.set_global_gen(gen) - # P2: 注入 HandlesType 模块级单例(委托函数经本地 _g_gen 访问, + # P2: 注入 HandlesType/HandlesStruct 模块级单例(委托函数经本地 _g_gen 访问, # 避免函数体 import 包模块与 Generator 类/模块名歧义) HandlesType.set_global_gen(gen) + HandlesStruct.set_global_gen(gen) # 设置当前文件名(供报错使用) HandlesType.set_current_file(file_path) # 同步到 HandlesImports(import 时 SHA1 检查报错需要当前文件名,循环依赖无法直接读 HandlesType) diff --git a/App/lib/core/Gen/Generator.vp b/App/lib/core/Gen/Generator.vp index 86984c0..eca5d87 100644 --- a/App/lib/core/Gen/Generator.vp +++ b/App/lib/core/Gen/Generator.vp @@ -4,6 +4,7 @@ import memhub import llvmlite import lib.core.Gen.BaseGenMixin as BaseGenMixin import lib.core.Gen.TypeGenMixin as TypeGenMixin +import lib.core.Gen.StructGenMixin as StructGenMixin import lib.core.Handles.HandlesVar as HandlesVar import lib.core.Handles.HandlesExprCall as HandlesExprCall @@ -21,7 +22,8 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall # 全部内联,不调用父类 Init* 方法。 # ============================================================ @t.NoVTable -class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin): +class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin, + StructGenMixin.StructGenMixin): """生成器:多继承 Mixin 组合(对象化迁移宿主)""" def __init__(self, pool: memhub.MemBuddy | t.CPtr): @@ -59,6 +61,12 @@ class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin): self.CTypedefVisiting = None self.CurrentFile = None self.ConstEvalOk = 0 + # ---- StructGenMixin 字段 ---- + self.StructTable = None + self.StructCount = 0 + self.StdlibAlloc = 0 + self.VisibleStructs = None + self.StrictVisibility = 0 # ============================================================ diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp new file mode 100644 index 0000000..8d5f539 --- /dev/null +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -0,0 +1,1037 @@ +import t, c +from stdint import * +import memhub +import string +import stdlib +import llvmlite +import stdio +import ast +import hashtable +import viperlib +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesStruct as HandlesStruct + + +# ============================================================ +# StructGenMixin - 结构体注册/字段查找 Mixin(对象化 P2-2,wiki/14-oo-refactor.md) +# +# 从 HandlesStruct.vp 迁移: +# 全局状态(_struct_table/_struct_count/_g_stdlib_alloc/ +# _visible_structs/_strict_visibility)→ 本类字段 +# 模块级函数(register_struct/find_struct/lookup_field/...)→ 本类方法 +# +# 迁移原则(与 TypeGenMixin P2-1 一致,行为零变化): +# 1. 方法保留原函数签名(含 pool 首参),仅函数体内的全局变量改为 self.字段 +# 2. HandlesStruct.vp 原函数保留为"委托":本地模块级单例 _g_gen(BuildPipeline +# /main 注入)cast 成 Generator 类型后调本类方法 +# 3. FieldEntry/StructEntry 类型保留在 HandlesStruct.vp(本类字段引用) +# +# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。 +# ============================================================ + + +# ============================================================ +# 常量(与 HandlesStruct 保持一致) +# ============================================================ +STRUCT_MAX: t.CDefine = 512 +FIELD_MAX: t.CDefine = 48 +FIELD_NAME_MAX: t.CDefine = 64 +PARENT_MAX: t.CDefine = 8 +MRO_MAX: t.CDefine = 16 + + +# ============================================================ +# StructGenMixin - 结构体注册表/字段查找/可见性 +# ============================================================ +@t.NoVTable +class StructGenMixin: + """结构体注册与查找 Mixin(状态从 HandlesStruct 全局变量迁入)""" + + # --- 全局注册表(原 _struct_table/_struct_count) --- + StructTable: HandlesStruct.StructEntry | t.CPtr # STRUCT_MAX 槽位数组 + StructCount: int + + # --- OOM 回收分配模式(原 _g_stdlib_alloc) --- + StdlibAlloc: int + + # --- 跨模块命名空间隔离(原 _visible_structs/_strict_visibility) --- + VisibleStructs: hashtable.HashTable | t.CPtr + StrictVisibility: int + + def InitStructGen(self) -> int: + """初始化结构体 Mixin 字段(子类构造时内联调用,规避 NoVTable 继承符号不转发)""" + if self is None: + return 1 + self.StructTable = None + self.StructCount = 0 + self.StdlibAlloc = 0 + self.VisibleStructs = None + self.StrictVisibility = 0 + return 0 + + # ============================================================ + # P2-2 迁移方法(函数体来自 HandlesStruct.vp,全局变量改 self.字段, + # 同模块函数调用改 self.方法;签名与 HandlesStruct 原函数一致) + # ============================================================ + + def set_stdlib_alloc(self, flag: int): + """设置 OOM 回收分配模式:1=1b 阶段(新条目用 stdlib),0=注册阶段(用 pool)""" + self.StdlibAlloc = flag + + def reset_visible_structs(self, pool: memhub.MemBuddy | t.CPtr, strict: int): + """重置可见性状态(每个文件翻译前调用) + + pool: 内存分配器(严格模式下创建 HashTable) + strict: 1=严格模式(用户文件),0=宽松模式(includes 文件) + """ + self.StrictVisibility = strict + if strict != 0: + # 严格模式:创建新的 HashTable 记录可见结构体 + self.VisibleStructs = hashtable.HashTable(pool) + else: + # 宽松模式:全部可见,不需要 HashTable + self.VisibleStructs = None + + def add_visible_struct(self, pool: memhub.MemBuddy | t.CPtr, name: str): + """添加可见结构体名(类定义时和 from-import 时调用)""" + if name is None: + return + # 宽松模式:全部可见,无需记录 + if self.StrictVisibility == 0: + return + if self.VisibleStructs is None: + return + # 已存在则跳过(HashTable.__setitem__ 会覆盖,此处提前检查避免重复分配) + if self.VisibleStructs.__contains__(name) != 0: + return + self.VisibleStructs.set_int(name, 1) + + def is_struct_visible(self, name: str) -> int: + """检查结构体是否可见,返回 1=可见 / 0=不可见""" + if self.StrictVisibility == 0: + return 1 + if name is None or self.VisibleStructs is None: + return 0 + return self.VisibleStructs.__contains__(name) + + def init_struct_table(self, pool: memhub.MemBuddy | t.CPtr) -> int: + """初始化结构体注册表,返回 1 成功""" + if self.StructTable is not None: + return 1 + + entry_size: t.CSizeT = HandlesStruct.StructEntry.__sizeof__() + self.StructTable = pool.alloc(entry_size * STRUCT_MAX) + if self.StructTable is None: + return 0 + string.memset(self.StructTable, 0, entry_size * STRUCT_MAX) + self.StructCount = 0 + return 1 + + def _get_struct_entry(self, i: int) -> HandlesStruct.StructEntry | t.CPtr: + """获取第 i 个结构体条目""" + if self.StructTable is None or i < 0 or i >= STRUCT_MAX: + return None + entry_size: t.CSizeT = HandlesStruct.StructEntry.__sizeof__() + addr: t.CUInt64T = t.CUInt64T(self.StructTable) + i * entry_size + return (HandlesStruct.StructEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) + + def _get_field_entry(self, struct_entry: HandlesStruct.StructEntry | t.CPtr, i: int) -> HandlesStruct.FieldEntry | t.CPtr: + """获取结构体中第 i 个字段条目""" + if struct_entry is None or i < 0 or i >= FIELD_MAX: + return None + field_size: t.CSizeT = HandlesStruct.FieldEntry.__sizeof__() + addr: t.CUInt64T = t.CUInt64T(struct_entry.Fields) + i * field_size + return (HandlesStruct.FieldEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) + + def register_struct(self, pool: memhub.MemBuddy | t.CPtr, + name: str, + struct_ty: llvmlite.LLVMType | t.CPtr, + sha1: str = None) -> HandlesStruct.StructEntry | t.CPtr: + """注册结构体类型,返回 StructEntry 指针 + + 用类型指针去重(is 比较),不用类名去重。 + 这样跨模块同名类可以共存,各自有独立的字段定义。 + sha1 参数在注册时直接设置 ModuleSha1(避免 set_struct_sha1 找错 entry)。 + """ + if self.init_struct_table(pool) == 0: + return None + + # 用类型指针去重(同一类型不重复注册,支持跨模块同名类) + # 用 t.CUInt64T 指针值比较(is 比较会触发类型安全检查解引用悬空 Ty) + st_dedup: t.CUInt64T = t.CUInt64T(struct_ty) + for i in range(self.StructCount): + existing: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if existing is not None and existing.Ty is not None: + if t.CUInt64T(existing.Ty) == st_dedup: + return existing + + if self.StructCount >= STRUCT_MAX: + fb_st: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_st is not None: + viperlib.snprintf(fb_st, 1024, "table full, cannot register %s", name) + VLogger.error(fb_st, "STRUCT") + return None + + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(self.StructCount) + if entry is None: + return None + + # 分配字段数组(1b 阶段用 stdlib,避免 reset 回收后 Fields 悬空) + field_size: t.CSizeT = HandlesStruct.FieldEntry.__sizeof__() + if self.StdlibAlloc != 0: + entry.Fields = stdlib.malloc(field_size * FIELD_MAX) + else: + entry.Fields = pool.alloc(field_size * FIELD_MAX) + if entry.Fields is None: + return None + string.memset(entry.Fields, 0, field_size * FIELD_MAX) + + # 复制类名(1b 阶段用 stdlib) + name_len: t.CSizeT = string.strlen(name) + if self.StdlibAlloc != 0: + name_buf: t.CChar | t.CPtr = stdlib.malloc(name_len + 1) + else: + name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) + if name_buf is not None: + string.strcpy(name_buf, name) + entry.Name = name_buf + + entry.Ty = struct_ty + entry.FieldCount = 0 + + # 注册时直接设置 SHA1(避免 set_struct_sha1 跨模块同名时找错 entry) + if sha1 is not None: + sha1_len: t.CSizeT = string.strlen(sha1) + if self.StdlibAlloc != 0: + sha1_buf: t.CChar | t.CPtr = stdlib.malloc(sha1_len + 1) + else: + sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) + if sha1_buf is not None: + string.strcpy(sha1_buf, sha1) + entry.ModuleSha1 = sha1_buf + + self.StructCount += 1 + return entry + + def set_struct_sha1(self, pool: memhub.MemBuddy | t.CPtr, + class_name: str, sha1: str) -> int: + """设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败""" + if class_name is None or sha1 is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(class_name) + if entry is None: + return 0 + # 复制 SHA1 字符串(避免悬空指针) + sha1_len: t.CSizeT = string.strlen(sha1) + sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) + if sha1_buf is None: + return 0 + string.strcpy(sha1_buf, sha1) + entry.ModuleSha1 = sha1_buf + return 1 + + def get_struct_sha1(self, class_name: str) -> str: + """获取结构体所属模块的 SHA1,返回 None=无 SHA1""" + if class_name is None or self.StructTable is None: + return None + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(class_name) + if entry is None: + return None + return entry.ModuleSha1 + + def add_field(self, pool: memhub.MemBuddy | t.CPtr, + struct_entry: HandlesStruct.StructEntry | t.CPtr, + field_name: str, + field_ty: llvmlite.LLVMType | t.CPtr, + default_val: ast.AST | t.CPtr = None, + annot_class_name: t.CChar | t.CPtr = None) -> int: + """向结构体添加字段,返回字段索引(-1 失败) + + default_val: 字段默认值 AST 节点(可选,None=无默认值) + annot_class_name: 原始类型注解的类名(可选,用于联合类型字段的方法调用解析) + """ + if struct_entry is None or field_name is None or field_ty is None: + return -1 + + if struct_entry.FieldCount >= FIELD_MAX: + fb_sf: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_sf is not None: + viperlib.snprintf(fb_sf, 1024, "field table full for %s", struct_entry.Name) + VLogger.error(fb_sf, "STRUCT") + return -1 + + idx: int = struct_entry.FieldCount + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(struct_entry, idx) + if fe is None: + return -1 + + # 复制字段名(1b 阶段用 stdlib,避免 reset 回收后 fe.Name 悬空) + name_len: t.CSizeT = string.strlen(field_name) + if self.StdlibAlloc != 0: + name_buf: t.CChar | t.CPtr = stdlib.malloc(name_len + 1) + else: + name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) + if name_buf is not None: + string.strcpy(name_buf, field_name) + fe.Name = name_buf + + fe.Index = idx + fe.Ty = field_ty + fe.DefaultVal = default_val + fe.AnnotClassName = annot_class_name + + struct_entry.FieldCount = idx + 1 + return idx + + def get_struct_count(self) -> int: + """返回当前已注册的结构体数量""" + return self.StructCount + + def find_struct(self, name: str) -> HandlesStruct.StructEntry | t.CPtr: + """按类名查找结构体,返回 StructEntry 或 None + + 支持模块限定名(如 "HT.Translator"): + 第一遍精确匹配,第二遍按类名(最后一个 '.' 之后的部分)回退 + """ + if name is None or self.StructTable is None: + return None + # 第一遍:精确匹配 + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Name is not None: + if string.strcmp(entry.Name, name) == 0: + return entry + # 第二遍:类名回退(处理模块限定名 "HT.Translator" → "Translator") + dot_pos: str = string.strrchr(name, '.') + if dot_pos is not None: + class_name: str = dot_pos + 1 + if class_name is not None and class_name[0] != '\0': + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Name is not None: + if string.strcmp(entry.Name, class_name) == 0: + return entry + return None + + def find_struct_by_module(self, name: str, sha1: str) -> HandlesStruct.StructEntry | t.CPtr: + """按类名 + SHA1 查找结构体,返回 StructEntry 或 None + + SHA1 非 None 时:精确匹配 name+sha1,未找到返回 None(不回退,避免跨模块同名找错) + SHA1 为 None 时:回退到 find_struct(name) 按类名查找第一个 + """ + if name is None or self.StructTable is None: + return None + if sha1 is not None: + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Name is not None: + if string.strcmp(entry.Name, name) == 0: + if entry.ModuleSha1 is not None: + if string.strcmp(entry.ModuleSha1, sha1) == 0: + return entry + # SHA1 查找失败:不回退到 find_struct(会返回跨模块同名错误 entry) + # 返回 None 让调用方创建新类型,避免 Phase B 用错误类型短路 + return None + # 无 SHA1:按类名查找第一个 + return self.find_struct(name) + + def find_struct_by_type(self, struct_ty: llvmlite.LLVMType | t.CPtr) -> HandlesStruct.StructEntry | t.CPtr: + """按类型指针查找结构体(指针值比较),返回 StructEntry 或 None + + 注意: 不能用 `entry.Ty is struct_ty` 的 is 比较——TPV 编译 is 时会触发 + translate_compare 的类型安全检查(is_ptr_type/TypePrint 递归打印), + 对悬空 entry.Ty(1b 泛型特化类注册后被 reset 回收的 pool 指针)解引用崩溃。 + 改用 t.CUInt64T 纯指针值比较,不解引用任何内容。 + """ + if struct_ty is None or self.StructTable is None: + return None + st_val: t.CUInt64T = t.CUInt64T(struct_ty) + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Ty is not None: + if t.CUInt64T(entry.Ty) == st_val: + return entry + return None + + def lookup_field(self, struct_ty: llvmlite.LLVMType | t.CPtr, + field_name: str) -> HandlesStruct.FieldEntry | t.CPtr: + """按结构体类型和字段名查找字段信息 + + 两遍查找策略(跨模块同名类冲突的根本修复): + 第一遍: 类型指针 is 身份比较(最高优先级,类型唯一确定 entry) + 第二遍: 名称回退(is 未匹配时,按类名/strstr 匹配,字段未找到时 continue) + """ + if struct_ty is None or field_name is None or self.StructTable is None: + return None + + # ============================================================ + # 两遍查找策略(跨模块同名类冲突的根本修复): + # + # 第一遍: 用类型指针 is 身份比较(最高优先级) + # - is 匹配唯一确定 entry,字段未找到直接返回 None + # - 规避联合类型 == BUG,且不受遍历顺序影响 + # + # 第二遍: 名称回退(is 未匹配到任何 entry 时才执行) + # - 用于未注册类型或 is 不可靠的场景 + # - 名称匹配但字段未找到时 continue(继续检查其他同名 entry) + # ============================================================ + + # 第一遍: is 身份比较(用 t.CUInt64T 指针值比较,避免 is 编译路径解引用悬空 Ty) + st_lk: t.CUInt64T = t.CUInt64T(struct_ty) + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Ty is not None: + if t.CUInt64T(entry.Ty) == st_lk: + # is 匹配,查找字段 + for fi in range(entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(entry, fi) + if fe is not None and fe.Name is not None: + if string.strcmp(fe.Name, field_name) == 0: + return fe + # is 匹配但字段未找到(类型唯一确定,无需继续) + return None + + # 第二遍: 名称回退(is 未匹配到) + ty_name: str = self._extract_struct_name(struct_ty) + if ty_name is not None: + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Name is not None: + matched: int = 0 + if string.strcmp(entry.Name, ty_name) == 0: + matched = 1 + elif string.strstr(ty_name, entry.Name) is not None: + matched = 1 + if matched != 0: + # 查找字段 + for fi in range(entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(entry, fi) + if fe is not None and fe.Name is not None: + if string.strcmp(fe.Name, field_name) == 0: + return fe + # 名称匹配但字段未找到,继续检查其他同名 entry(跨模块同名) + continue + # 所有条目都未匹配 + return None + + def lookup_field_by_class(self, class_name: str, + field_name: str, + sha1: str = None) -> HandlesStruct.FieldEntry | t.CPtr: + """按类名和字段名查找字段信息 + + 优先用 SHA1 匹配(跨模块同名类区分),无 SHA1 时按类名查找第一个 + """ + if class_name is None or field_name is None: + return None + + # 优先用 SHA1 匹配(跨模块同名类区分) + # 支持模块限定名:class_name 可能是 "HT.Translator",entry.Name 是 "Translator" + # 先精确匹配,失败后用 strrchr 提取类名部分回退匹配 + if sha1 is not None: + sha1_matched: int = 0 + # 计算类名回退部分("HT.Translator" → "Translator") + bare_name: str = class_name + dot_pos_lfbc: str = string.strrchr(class_name, '.') + if dot_pos_lfbc is not None: + bare_name = dot_pos_lfbc + 1 + if bare_name is None or bare_name[0] == '\0': + bare_name = class_name + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Name is not None: + # 精确匹配或类名回退匹配 + name_match: int = 0 + if string.strcmp(entry.Name, class_name) == 0: + name_match = 1 + elif bare_name is not class_name and string.strcmp(entry.Name, bare_name) == 0: + name_match = 1 + if name_match != 0: + if entry.ModuleSha1 is not None: + if string.strcmp(entry.ModuleSha1, sha1) == 0: + sha1_matched = 1 + # SHA1 + 类名匹配,查找字段 + for fi in range(entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(entry, fi) + if fe is not None and fe.Name is not None: + if string.strcmp(fe.Name, field_name) == 0: + return fe + return None + + # 回退: 无 SHA1 或 SHA1 匹配失败,按类名查找第一个 + entry = self.find_struct(class_name) + if entry is None: + # 诊断:目标类未注册 + fb_lfbc: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_lfbc is not None: + viperlib.snprintf(fb_lfbc, 1024, + "lookup_field_by_class: 类 '%s' 未注册 (struct_count=%d)", + class_name, self.StructCount) + VLogger.error(fb_lfbc, "STRUCT") + return None + # 诊断:找到结构体但字段未找到,打印字段表 + fb_fields: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_fields is not None: + viperlib.snprintf(fb_fields, 1024, + "lookup_field_by_class: 类 '%s' 已注册 (FieldCount=%d) 但字段 '%s' 未找到", + class_name, entry.FieldCount, field_name) + VLogger.error(fb_fields, "STRUCT") + for fi in range(entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(entry, fi) + if fe is not None and fe.Name is not None: + fb_fn: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_fn is not None: + viperlib.snprintf(fb_fn, 1024, " 字段[%d]: %s", fi, fe.Name) + VLogger.error(fb_fn, "STRUCT") + for fi in range(entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(entry, fi) + if fe is not None and fe.Name is not None: + if string.strcmp(fe.Name, field_name) == 0: + return fe + # 诊断:找到结构体但字段未找到 + return None + + def get_struct_type(self, class_name: str) -> llvmlite.LLVMType | t.CPtr: + """按类名获取结构体的 LLVM 类型""" + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(class_name) + if entry is not None: + return entry.Ty + return None + + def get_field_by_index(self, class_name: str, + idx: int) -> HandlesStruct.FieldEntry | t.CPtr: + """按类名和字段索引获取字段信息""" + if class_name is None: + return None + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(class_name) + if entry is None: + return None + if idx < 0 or idx >= entry.FieldCount: + return None + return self._get_field_entry(entry, idx) + + def struct_has_defaults(self, class_name: str) -> int: + """检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无""" + if class_name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(class_name) + if entry is None: + return 0 + for fi in range(entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = self._get_field_entry(entry, fi) + if fe is not None and fe.DefaultVal is not None: + return 1 + return 0 + + def get_struct_type_from_value(self, val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr: + """从 Value 的类型推断结构体类型""" + if val is None or val.Ty is None: + return None + # 嵌套 match:先匹配 Ptr,再在 case 块内匹配 pointee 是否为 Struct + match val.Ty: + case llvmlite.LLVMType.Ptr(pointee): + match pointee: + case llvmlite.LLVMType.Struct(fields, fcount, name): + return pointee + case _: + return None + case _: + return None + + def mark_as_union(self, name: str) -> int: + """标记已注册的结构体为联合体,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.IsUnion = 1 + return 1 + + def is_union_by_name(self, name: str) -> int: + """按类名检查是否为联合体,返回 1=是 / 0=否""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.IsUnion + + def is_union_by_type(self, struct_ty: llvmlite.LLVMType | t.CPtr) -> int: + """按类型指针检查是否为联合体,返回 1=是 / 0=否 + + 先尝试类型指针 == 比较,失败时回退到名称匹配 + """ + if struct_ty is None or self.StructTable is None: + return 0 + ty_name: str = self._extract_struct_name(struct_ty) + st_iu: t.CUInt64T = t.CUInt64T(struct_ty) + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Ty is not None: + matched: int = 0 + if t.CUInt64T(entry.Ty) == st_iu: + matched = 1 + elif ty_name is not None and entry.Name is not None: + if string.strcmp(entry.Name, ty_name) == 0: + matched = 1 + elif string.strstr(ty_name, entry.Name) is not None: + matched = 1 + if matched != 0: + return entry.IsUnion + return 0 + + def mark_as_oop(self, name: str) -> int: + """标记已注册的结构体为 OOP,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.IsOOP = 1 + return 1 + + def is_oop_by_name(self, name: str) -> int: + """按类名检查是否为 OOP 结构体,返回 1=是 / 0=否""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.IsOOP + + def mark_has_init(self, name: str) -> int: + """标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.HasInit = 1 + return 1 + + def has_init_by_name(self, name: str) -> int: + """按类名检查是否有 __init__ 方法,返回 1=有 / 0=无""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.HasInit + + def mark_has_new(self, name: str) -> int: + """标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.HasNew = 1 + return 1 + + def has_new_by_name(self, name: str) -> int: + """按类名检查是否有 __new__ 方法,返回 1=有 / 0=无""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.HasNew + + def get_class_name_by_type(self, pool: memhub.MemBuddy | t.CPtr, + struct_ty: llvmlite.LLVMType | t.CPtr) -> str: + """按类型指针查找类名,返回类名字符串或 None""" + if struct_ty is None or self.StructTable is None: + return None + st_cn: t.CUInt64T = t.CUInt64T(struct_ty) + for i in range(self.StructCount): + entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Ty is not None: + if t.CUInt64T(entry.Ty) == st_cn: + return entry.Name + # 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配 + # 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式) + ty_name: str = self._extract_struct_name(struct_ty) + if ty_name is not None: + for j in range(self.StructCount): + entry2: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(j) + if entry2 is not None and entry2.Name is not None: + # 构造 "SHA1.ClassName" 格式进行比较 + entry2_sha1: str = entry2.ModuleSha1 + if entry2_sha1 is not None: + full_nm: t.CChar | t.CPtr = pool.alloc(128) + if full_nm is not None: + viperlib.snprintf(full_nm, 128, "%s.%s", entry2_sha1, entry2.Name) + if string.strcmp(full_nm, ty_name) == 0: + return entry2.Name + # 也直接比较类名(struct_ty 的 Name 可能无 SHA1 前缀) + if string.strcmp(entry2.Name, ty_name) == 0: + return entry2.Name + # 最后回退: strstr 检查包含关系 + # ty_name 可能是 "SHA1.Counter",entry2.Name 是 "Counter" + if string.strstr(ty_name, entry2.Name) is not None: + return entry2.Name + return None + + def _extract_struct_name(self, ty: llvmlite.LLVMType | t.CPtr) -> str: + """从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct""" + if ty is None: + return None + match ty: + case llvmlite.LLVMType.Struct(fields, fcount, name): + return name + case _: + return None + + def mark_has_vtable(self, name: str) -> int: + """标记结构体拥有虚表,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.HasVTable = 1 + return 1 + + def has_vtable_by_name(self, name: str) -> int: + """按类名检查是否有虚表,返回 1=有 / 0=无""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.HasVTable + + def mark_novtable(self, name: str) -> int: + """标记结构体为 NoVTable,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.IsNoVTable = 1 + return 1 + + def is_novtable_by_name(self, name: str) -> int: + """按类名检查是否为 NoVTable,返回 1=是 / 0=否""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.IsNoVTable + + def set_parent_name(self, name: str, parent_name: str) -> int: + """设置结构体的父类名,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.ParentName = parent_name + return 1 + + def set_parent_names(self, name: str, names_ptr: t.CSizeT | t.CPtr, + count: int) -> int: + """设置结构体的父类名数组(stdlib 深拷贝,跨文件永久存活)""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + if names_ptr is None or count <= 0: + entry.ParentNames = None + entry.ParentCount = 0 + return 1 + if count > PARENT_MAX: + count = PARENT_MAX + arr: t.CSizeT | t.CPtr = stdlib.malloc(8 * count) + if arr is None: + return 0 + for i in range(count): + addr: t.CSizeT = names_ptr[i] + arr[i] = 0 + if addr != 0: + src: str = (str | t.CPtr)(t.CVoid(addr, t.CPtr)) + if src is not None: + slen: t.CSizeT = string.strlen(src) + dup: t.CChar | t.CPtr = stdlib.malloc(slen + 1) + if dup is not None: + string.strcpy(dup, src) + arr[i] = t.CSizeT(dup) + entry.ParentNames = t.CSizeT(arr) + entry.ParentCount = count + return 1 + + def get_parent_count(self, name: str) -> int: + """获取父类数量(0=无父类,1=单继承,>1=多继承)""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.ParentCount + + def get_parent_name_at(self, name: str, idx: int) -> str: + """获取第 idx 个父类名,越界返回 None""" + if name is None or idx < 0: + return None + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None or entry.ParentNames is None: + return None + if idx >= entry.ParentCount: + return None + parr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.ParentNames, t.CPtr)) + addr: t.CSizeT = parr[idx] + if addr == 0: + return None + return (str | t.CPtr)(t.CVoid(addr, t.CPtr)) + + def get_mro_chain(self, pool: memhub.MemBuddy | t.CPtr, + name: str) -> t.CSizeT | t.CPtr: + """MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身)""" + if pool is None or name is None: + return None + arr: t.CSizeT | t.CPtr = pool.alloc(8 * (MRO_MAX + 1)) + if arr is None: + return None + stack: t.CSizeT | t.CPtr = pool.alloc(8 * MRO_MAX) + if stack is None: + return None + visited: t.CSizeT | t.CPtr = pool.alloc(8 * MRO_MAX) + if visited is None: + return None + stack_count: int = 0 + out_count: int = 0 + visit_count: int = 0 + # 初始压入自身 + stack[0] = t.CSizeT(name) + stack_count = 1 + while stack_count > 0: + stack_count -= 1 + cur_addr: t.CSizeT = stack[stack_count] + cur: str = (str | t.CPtr)(t.CVoid(cur_addr, t.CPtr)) + if cur is None: + continue + # 已访问检查(线性搜索) + dup: int = 0 + for vi in range(visit_count): + va: t.CSizeT = visited[vi] + if va != 0: + vn: str = (str | t.CPtr)(t.CVoid(va, t.CPtr)) + if vn is not None and string.strcmp(vn, cur) == 0: + dup = 1 + break + if dup != 0: + continue + # 加入结果与已访问集合 + if out_count < MRO_MAX: + arr[out_count] = t.CSizeT(cur) + out_count += 1 + if visit_count < MRO_MAX: + visited[visit_count] = t.CSizeT(cur) + visit_count += 1 + # 父类逆序压栈(正向 range 计算逆序索引,保证声明顺序弹出) + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(cur) + if entry is not None and entry.ParentCount > 0 and entry.ParentNames is not None: + pc: int = entry.ParentCount + parr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.ParentNames, t.CPtr)) + for pi2 in range(pc): + pi: int = pc - 1 - pi2 + if stack_count < MRO_MAX: + stack[stack_count] = parr[pi] + stack_count += 1 + # 末尾 0 结束 + arr[out_count] = 0 + return arr + + def get_parent_name(self, name: str) -> str: + """获取结构体的父类名,返回 None=无父类""" + if name is None: + return None + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return None + return entry.ParentName + + def set_vtable_methods(self, name: str, methods: t.CChar | t.CPtr, count: int) -> int: + """设置虚表方法名数组,返回 1=成功 / 0=失败""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + entry.VTableMethods = methods + entry.VTableMethodCount = count + return 1 + + def get_vtable_method_index(self, name: str, method_name: str) -> int: + """获取方法在虚表中的索引,返回 -1=未找到""" + if name is None or method_name is None: + return -1 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None or entry.VTableMethods is None: + return -1 + # VTableMethods 字段声明为 t.CChar*,但实际存储的是 t.CSizeT 数组 + # 必须转换为 t.CSizeT* 才能正确读取 8 字节指针值 + methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr)) + for i in range(entry.VTableMethodCount): + mname_addr: t.CSizeT = methods_arr[i] + if mname_addr == 0: + continue + mname: str = (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) + if mname is not None and string.strcmp(mname, method_name) == 0: + return i + return -1 + + def get_vtable_method_count(self, name: str) -> int: + """获取虚表方法数量""" + if name is None: + return 0 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return 0 + return entry.VTableMethodCount + + def get_vtable_method_name(self, name: str, idx: int) -> str: + """获取虚表中第 idx 个方法名,返回 None=越界""" + if name is None or idx < 0: + return None + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None or entry.VTableMethods is None: + return None + if idx >= entry.VTableMethodCount: + return None + methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr)) + mname_addr: t.CSizeT = methods_arr[idx] + if mname_addr == 0: + return None + return (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) + + def get_field_count(self, name: str) -> int: + """获取结构体字段数量,返回 -1=未找到""" + if name is None: + return -1 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct(name) + if entry is None: + return -1 + return entry.FieldCount + + def ensure_struct_def_in_module(self, pool: memhub.MemBuddy | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + ty: llvmlite.LLVMType | t.CPtr): + """确保跨模块结构体的完整定义在当前模块中可用(供 alloca 使用) + + 处理两种情况: + 1. Struct 值类型:需要完整定义(供 alloca 分配空间) + 2. Ptr(Struct) 指针类型:需要 pointee 至少有 opaque 声明 + """ + if ty is None or mod is None or pool is None: + return + # 指针类型:确保 pointee 至少有 opaque 声明 + match ty: + case llvmlite.LLVMType.Ptr(pointee): + llvmlite.module_ensure_opaque_for_type(mod, pool, ty) + # 如果 pointee 是 Struct,递归复制完整定义 + # (GEP 访问字段需要 sized 类型,仅 opaque 会导致 llc 报错) + if pointee is not None: + self.ensure_struct_def_in_module(pool, mod, pointee) + return + case _: + pass + # 获取结构体名称(非 Struct 类型返回 None) + sname: t.CChar | t.CPtr = llvmlite.get_struct_name(ty) + if sname is None: + return + # 检查是否为跨模块引用(名称包含 '.') + if string.strchr(sname, 46) is None: + return # 非跨模块引用,无需处理 + # 提取类名(第一个 '.' 之后的部分) + # 必须用 strchr 而非 strrchr:泛型特化名如 "list[ast.AST|t.CPtr]" + # 内部含 '.'(ast.AST),strrchr 会错误地把类名解析为 "AST|t.CPtr]" + dot_pos: str = string.strchr(sname, '.') + if dot_pos is None: + return + class_name: str = dot_pos + 1 + if class_name is None or class_name[0] == '\0': + return + # 提取 SHA1(sname 到 dot_pos 之间,用 strlen 避免指针减法) + total_len: t.CSizeT = string.strlen(sname) + class_name_len: t.CSizeT = string.strlen(class_name) + sha1_len: t.CSizeT = total_len - class_name_len - 1 + sha1_buf: t.CChar | t.CPtr = pool.alloc(32) + if sha1_buf is None: + return + string.strncpy(sha1_buf, sname, sha1_len) + sha1_buf[sha1_len] = '\0' + # 按类名 + SHA1 查找结构体定义 + entry: HandlesStruct.StructEntry | t.CPtr = self.find_struct_by_module(class_name, sha1_buf) + if entry is None: + # 回退到按类名查找(可能找到不同模块的同名类,但总比没有好) + entry = self.find_struct(class_name) + if entry is None: + return + if entry.Ty is None: + return + # 将完整定义添加到当前模块(会替换已存在的 opaque 声明) + llvmlite.module_add_named_type(mod, pool, entry.Ty) + # 递归扫描字段类型,确保值类型子结构体(如 WIN32_FIND_DATAA 中的 FILETIME) + # 也有完整定义。指针类型字段只需 opaque 声明(已由 module_ensure_opaque_for_type 处理)。 + self._ensure_field_types_in_module(pool, mod, entry.Ty) + + def _ensure_field_types_in_module(self, pool: memhub.MemBuddy | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + ty: llvmlite.LLVMType | t.CPtr): + """递归扫描类型树,确保值类型子结构体有完整定义""" + if ty is None or mod is None or pool is None: + return + # 嵌套 match 遍历类型树 + match ty: + case llvmlite.LLVMType.Struct(fields, fcount, sname): + # 遍历字段链表 + if fields is not None: + fld: llvmlite.ParamNode | t.CPtr = fields + while fld is not None: + if fld.Ty is not None: + # 值类型子结构体(如 FILETIME)需要完整定义 + match fld.Ty: + case llvmlite.LLVMType.Struct(f2, fc2, n2): + self.ensure_struct_def_in_module(pool, mod, fld.Ty) + case _: + pass + self._ensure_field_types_in_module(pool, mod, fld.Ty) + fld = fld.Next + case llvmlite.LLVMType.Ptr(pointee): + # 指针类型:pointee 只需 opaque 声明,不需要完整定义 + # 但如果 pointee 是 Struct,确保 opaque 声明存在 + if pointee is not None: + llvmlite.module_ensure_opaque_for_type(mod, pool, ty) + case llvmlite.LLVMType.Array(elem_ty, acount): + # 数组类型:元素如果是值类型结构体,需要完整定义 + if elem_ty is not None: + self._ensure_field_types_in_module(pool, mod, elem_ty) + case _: + pass + + def get_field_name_ptr(self, fe: HandlesStruct.FieldEntry | t.CPtr) -> str: + """获取 FieldEntry 的字段名,返回 None=未设置""" + if fe is None: + return None + return fe.Name + + def get_field_type_ptr(self, fe: HandlesStruct.FieldEntry | t.CPtr) -> llvmlite.LLVMType | t.CPtr: + """获取 FieldEntry 的字段类型,返回 None=未设置""" + if fe is None: + return None + return fe.Ty + + def get_field_default_ptr(self, fe: HandlesStruct.FieldEntry | t.CPtr) -> ast.AST | t.CPtr: + """获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值""" + if fe is None: + return None + return fe.DefaultVal + + def get_field_annot_class_name(self, fe: HandlesStruct.FieldEntry | t.CPtr) -> str: + """获取 FieldEntry 的原始类型注解类名,返回 None=未设置""" + if fe is None: + return None + return fe.AnnotClassName diff --git a/App/lib/core/Handles/HandlesStruct.vp b/App/lib/core/Handles/HandlesStruct.vp index 852aaf3..0d822e8 100644 --- a/App/lib/core/Handles/HandlesStruct.vp +++ b/App/lib/core/Handles/HandlesStruct.vp @@ -12,13 +12,19 @@ import lib.core.VLogger as VLogger # ============================================================ -# HandlesStruct - 结构体类型注册和字段查找 +# HandlesStruct - 结构体类型注册和字段查找(P2-2 对象化后的委托层) # # 管理 class 定义的结构体类型信息: # - 类名 → LLVM StructType # - 字段名 → 字段索引和类型 # -# 使用全局数组存储,线性查找(结构体数量通常很少) +# P2-2 对象化重构(wiki/14-oo-refactor.md): +# 全部函数已迁移为 lib.core.Gen.StructGenMixin 的方法(全局状态迁入 +# gen 字段),本模块保留同名模块级函数作为"一行委托":延迟 import +# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册), +# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。 +# +# FieldEntry/StructEntry 类型与常量保留在本模块(gen 字段类型引用)。 # ============================================================ STRUCT_MAX: t.CDefine = 512 @@ -66,1266 +72,516 @@ class StructEntry: # ============================================================ -# 全局注册表(静态分配) +# 全局 gen 单例(模块级镜像,同 HandlesType 模式) +# +# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。 +# P2-2 委托函数用本地 _g_gen(cast 成 Generator 类型)调 +# StructGenMixin 方法,避免函数体 import 包模块与 Generator +# 类/模块名歧义。 # ============================================================ -_struct_table: StructEntry | t.CPtr = None -_struct_count: int = 0 +_g_gen: t.CVoid | t.CPtr = None -# OOM 回收标志:1=后续 register_struct/add_field 的新分配用 stdlib(跨文件永久存活), -# 0=用 pool(mark1 前阶段,会被保留)。Phase1 在 1b 开始前设为 1。 -_g_stdlib_alloc: int = 0 + +def set_global_gen(gen: t.CVoid | t.CPtr) -> None: + """注入全局 gen 单例(BuildPipeline/main 调用)""" + global _g_gen + _g_gen = gen + + +# ============================================================ +# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法 +# (gen 未注册时正常流程不会发生;有返回值函数返回默认值) +# ============================================================ def set_stdlib_alloc(flag: int): - """设置 OOM 回收分配模式:1=1b 阶段(新条目用 stdlib),0=注册阶段(用 pool)""" - global _g_stdlib_alloc - _g_stdlib_alloc = flag + """设置 OOM 回收分配模式(委托到 gen.set_stdlib_alloc)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.set_stdlib_alloc(flag) -# ============================================================ -# 跨模块命名空间隔离:per-file 结构体可见性 -# -# _visible_structs: 当前文件可见的结构体名(HashTable,O(1) 查找) -# _strict_visibility: 1=严格模式(仅本地+import可见)/ 0=宽松模式(全部可见) -# -# 每个文件翻译前调用 reset_visible_structs 重置 -# ============================================================ -_visible_structs: hashtable.HashTable | t.CPtr = None -_strict_visibility: int = 0 - - -# ============================================================ -# reset_visible_structs — 重置可见性状态(每个文件翻译前调用) -# ============================================================ def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int): - """重置可见性状态(每个文件翻译前调用) - - pool: 内存分配器(严格模式下创建 HashTable) - strict: 1=严格模式(用户文件),0=宽松模式(includes 文件) - """ - global _visible_structs - global _strict_visibility - _strict_visibility = strict - if strict != 0: - # 严格模式:创建新的 HashTable 记录可见结构体 - _visible_structs = hashtable.HashTable(pool) - else: - # 宽松模式:全部可见,不需要 HashTable - _visible_structs = None + """重置可见性状态(每个文件翻译前调用,委托到 gen.reset_visible_structs)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.reset_visible_structs(pool, strict) -# ============================================================ -# add_visible_struct — 添加可见结构体名 -# ============================================================ def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str): - """添加可见结构体名(类定义时和 from-import 时调用)""" - global _visible_structs - if name is None: - return - # 宽松模式:全部可见,无需记录 - if _strict_visibility == 0: - return - if _visible_structs is None: - return - # 已存在则跳过(HashTable.__setitem__ 会覆盖,此处提前检查避免重复分配) - if _visible_structs.__contains__(name) != 0: - return - _visible_structs.set_int(name, 1) + """添加可见结构体名(类定义时和 from-import 时调用,委托到 gen.add_visible_struct)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.add_visible_struct(pool, name) -# ============================================================ -# is_struct_visible — 检查结构体是否在当前文件可见 -# ============================================================ def is_struct_visible(name: str) -> int: - """检查结构体是否可见,返回 1=可见 / 0=不可见""" - if _strict_visibility == 0: - return 1 - if name is None or _visible_structs is None: - return 0 - return _visible_structs.__contains__(name) + """检查结构体是否可见,返回 1=可见 / 0=不可见(委托到 gen.is_struct_visible)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_struct_visible(name) + return 0 -# ============================================================ -# 初始化结构体注册表 -# ============================================================ def init_struct_table(pool: memhub.MemBuddy | t.CPtr) -> int: - """初始化结构体注册表,返回 1 成功""" - global _struct_table, _struct_count - - if _struct_table is not None: - return 1 - - entry_size: t.CSizeT = StructEntry.__sizeof__() - _struct_table = pool.alloc(entry_size * STRUCT_MAX) - if _struct_table is None: - return 0 - string.memset(_struct_table, 0, entry_size * STRUCT_MAX) - _struct_count = 0 - return 1 + """初始化结构体注册表,返回 1 成功(委托到 gen.init_struct_table)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.init_struct_table(pool) + return 0 -# ============================================================ -# _get_struct_entry — 获取第 i 个 StructEntry 槽位 -# ============================================================ def _get_struct_entry(i: int) -> StructEntry | t.CPtr: - """获取第 i 个结构体条目""" - if _struct_table is None or i < 0 or i >= STRUCT_MAX: - return None - entry_size: t.CSizeT = StructEntry.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(_struct_table) + i * entry_size - return (StructEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) + """获取第 i 个结构体条目(委托到 gen._get_struct_entry)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_struct_entry(i) + return None -# ============================================================ -# _get_field_entry — 获取结构体中第 i 个 FieldEntry 槽位 -# ============================================================ def _get_field_entry(struct_entry: StructEntry | t.CPtr, i: int) -> FieldEntry | t.CPtr: - """获取结构体中第 i 个字段条目""" - if struct_entry is None or i < 0 or i >= FIELD_MAX: - return None - field_size: t.CSizeT = FieldEntry.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(struct_entry.Fields) + i * field_size - return (FieldEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) + """获取结构体中第 i 个字段条目(委托到 gen._get_field_entry)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_field_entry(struct_entry, i) + return None -# ============================================================ -# register_struct — 注册结构体类型 -# -# 返回 StructEntry 指针,可用于添加字段 -# ============================================================ def register_struct(pool: memhub.MemBuddy | t.CPtr, name: str, struct_ty: llvmlite.LLVMType | t.CPtr, sha1: str = None) -> StructEntry | t.CPtr: - global _struct_count - """注册结构体类型,返回 StructEntry 指针 - - 用类型指针去重(is 比较),不用类名去重。 - 这样跨模块同名类可以共存,各自有独立的字段定义。 - sha1 参数在注册时直接设置 ModuleSha1(避免 set_struct_sha1 找错 entry)。 - """ - if init_struct_table(pool) == 0: - return None - - # 用类型指针去重(同一类型不重复注册,支持跨模块同名类) - # 用 t.CUInt64T 指针值比较(is 比较会触发类型安全检查解引用悬空 Ty) - st_dedup: t.CUInt64T = t.CUInt64T(struct_ty) - for i in range(_struct_count): - existing: StructEntry | t.CPtr = _get_struct_entry(i) - if existing is not None and existing.Ty is not None: - if t.CUInt64T(existing.Ty) == st_dedup: - return existing - - if _struct_count >= STRUCT_MAX: - fb_st: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_st is not None: - viperlib.snprintf(fb_st, 1024, "table full, cannot register %s", name) - VLogger.error(fb_st, "STRUCT") - return None - - entry: StructEntry | t.CPtr = _get_struct_entry(_struct_count) - if entry is None: - return None - - # 分配字段数组(1b 阶段用 stdlib,避免 reset 回收后 Fields 悬空) - field_size: t.CSizeT = FieldEntry.__sizeof__() - if _g_stdlib_alloc != 0: - entry.Fields = stdlib.malloc(field_size * FIELD_MAX) - else: - entry.Fields = pool.alloc(field_size * FIELD_MAX) - if entry.Fields is None: - return None - string.memset(entry.Fields, 0, field_size * FIELD_MAX) - - # 复制类名(1b 阶段用 stdlib) - name_len: t.CSizeT = string.strlen(name) - if _g_stdlib_alloc != 0: - name_buf: t.CChar | t.CPtr = stdlib.malloc(name_len + 1) - else: - name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, name) - entry.Name = name_buf - - entry.Ty = struct_ty - entry.FieldCount = 0 - - # 注册时直接设置 SHA1(避免 set_struct_sha1 跨模块同名时找错 entry) - if sha1 is not None: - sha1_len: t.CSizeT = string.strlen(sha1) - if _g_stdlib_alloc != 0: - sha1_buf: t.CChar | t.CPtr = stdlib.malloc(sha1_len + 1) - else: - sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) - if sha1_buf is not None: - string.strcpy(sha1_buf, sha1) - entry.ModuleSha1 = sha1_buf - - _struct_count += 1 - return entry + """注册结构体类型,返回 StructEntry 指针(委托到 gen.register_struct)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.register_struct(pool, name, struct_ty, sha1) + return None -# ============================================================ -# set_struct_sha1 — 设置结构体所属模块的 SHA1 -# -# 在翻译类定义时调用,记录类所属模块的 SHA1。 -# 跨模块方法调用时(如 __before_init__/__init__),通过 SHA1 -# 构造正确的函数名("{sha1}.{ClassName}.{method}")。 -# ============================================================ def set_struct_sha1(pool: memhub.MemBuddy | t.CPtr, class_name: str, sha1: str) -> int: - """设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败""" - if class_name is None or sha1 is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return 0 - # 复制 SHA1 字符串(避免悬空指针) - sha1_len: t.CSizeT = string.strlen(sha1) - sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) - if sha1_buf is None: - return 0 - string.strcpy(sha1_buf, sha1) - entry.ModuleSha1 = sha1_buf - return 1 + """设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败(委托到 gen.set_struct_sha1)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.set_struct_sha1(pool, class_name, sha1) + return 0 -# ============================================================ -# get_struct_sha1 — 获取结构体所属模块的 SHA1 -# -# 跨模块方法调用时使用,返回 None=无 SHA1(本模块定义或无 SHA1) -# ============================================================ def get_struct_sha1(class_name: str) -> str: - """获取结构体所属模块的 SHA1,返回 None=无 SHA1""" - if class_name is None or _struct_table is None: - return None - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return None - return entry.ModuleSha1 + """获取结构体所属模块的 SHA1,返回 None=无 SHA1(委托到 gen.get_struct_sha1)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_struct_sha1(class_name) + return None -# ============================================================ -# add_field — 向结构体添加字段信息 -# ============================================================ def add_field(pool: memhub.MemBuddy | t.CPtr, struct_entry: StructEntry | t.CPtr, field_name: str, field_ty: llvmlite.LLVMType | t.CPtr, default_val: ast.AST | t.CPtr = None, annot_class_name: t.CChar | t.CPtr = None) -> int: - """向结构体添加字段,返回字段索引(-1 失败) - - default_val: 字段默认值 AST 节点(可选,None=无默认值) - annot_class_name: 原始类型注解的类名(可选,用于联合类型字段的方法调用解析) - """ - if struct_entry is None or field_name is None or field_ty is None: - return -1 - - if struct_entry.FieldCount >= FIELD_MAX: - fb_sf: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_sf is not None: - viperlib.snprintf(fb_sf, 1024, "field table full for %s", struct_entry.Name) - VLogger.error(fb_sf, "STRUCT") - return -1 - - idx: int = struct_entry.FieldCount - fe: FieldEntry | t.CPtr = _get_field_entry(struct_entry, idx) - if fe is None: - return -1 - - # 复制字段名(1b 阶段用 stdlib,避免 reset 回收后 fe.Name 悬空) - name_len: t.CSizeT = string.strlen(field_name) - if _g_stdlib_alloc != 0: - name_buf: t.CChar | t.CPtr = stdlib.malloc(name_len + 1) - else: - name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, field_name) - fe.Name = name_buf - - fe.Index = idx - fe.Ty = field_ty - fe.DefaultVal = default_val - fe.AnnotClassName = annot_class_name - - struct_entry.FieldCount = idx + 1 - return idx + """向结构体添加字段,返回字段索引(-1 失败,委托到 gen.add_field)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.add_field(pool, struct_entry, field_name, field_ty, + default_val, annot_class_name) + return 0 -# ============================================================ -# get_struct_count — 获取已注册结构体数量(供 Phase2 多遍预注册判断收敛) -# ============================================================ def get_struct_count() -> int: - """返回当前已注册的结构体数量""" - return _struct_count + """返回当前已注册的结构体数量(委托到 gen.get_struct_count)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_struct_count() + return 0 -# ============================================================ -# find_struct — 按类名查找结构体 -# ============================================================ def find_struct(name: str) -> StructEntry | t.CPtr: - """按类名查找结构体,返回 StructEntry 或 None - - 支持模块限定名(如 "HT.Translator"): - 第一遍精确匹配,第二遍按类名(最后一个 '.' 之后的部分)回退 - """ - if name is None or _struct_table is None: - return None - # 第一遍:精确匹配 - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry - # 第二遍:类名回退(处理模块限定名 "HT.Translator" → "Translator") - dot_pos: str = string.strrchr(name, '.') - if dot_pos is not None: - class_name: str = dot_pos + 1 - if class_name is not None and class_name[0] != '\0': - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, class_name) == 0: - return entry + """按类名查找结构体,返回 StructEntry 或 None(委托到 gen.find_struct)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.find_struct(name) return None -# ============================================================ -# find_struct_by_module — 按类名 + SHA1 查找结构体 -# -# 跨模块同名类区分:Phase B 重新翻译时,必须找到当前模块 -# 注册的结构体(而非第一个同名条目),否则 struct type、 -# 字段布局、GEP 索引全部错误。 -# ============================================================ def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr: - """按类名 + SHA1 查找结构体,返回 StructEntry 或 None - - SHA1 非 None 时:精确匹配 name+sha1,未找到返回 None(不回退,避免跨模块同名找错) - SHA1 为 None 时:回退到 find_struct(name) 按类名查找第一个 - """ - if name is None or _struct_table is None: - return None - if sha1 is not None: - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - if entry.ModuleSha1 is not None: - if string.strcmp(entry.ModuleSha1, sha1) == 0: - return entry - # SHA1 查找失败:不回退到 find_struct(会返回跨模块同名错误 entry) - # 返回 None 让调用方创建新类型,避免 Phase B 用错误类型短路 - return None - # 无 SHA1:按类名查找第一个 - return find_struct(name) - - -# ============================================================ -# find_struct_by_type — 按类型指针查找结构体(is 身份比较) -# -# 用于 _translate_oop_methods 等已有 struct_ty 的场景, -# 直接用指针身份定位 entry,规避跨模块同名类 find_struct 找错的问题。 -# ============================================================ -def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr: - """按类型指针查找结构体(指针值比较),返回 StructEntry 或 None - - 注意: 不能用 `entry.Ty is struct_ty` 的 is 比较——TPV 编译 is 时会触发 - translate_compare 的类型安全检查(is_ptr_type/TypePrint 递归打印), - 对悬空 entry.Ty(1b 泛型特化类注册后被 reset 回收的 pool 指针)解引用崩溃。 - 改用 t.CUInt64T 纯指针值比较,不解引用任何内容。 - """ - if struct_ty is None or _struct_table is None: - return None - st_val: t.CUInt64T = t.CUInt64T(struct_ty) - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - if t.CUInt64T(entry.Ty) == st_val: - return entry + """按类名 + SHA1 查找结构体,返回 StructEntry 或 None(委托到 gen.find_struct_by_module)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.find_struct_by_module(name, sha1) + return None + + +def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr: + """按类型指针查找结构体(指针值比较),返回 StructEntry 或 None(委托到 gen.find_struct_by_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.find_struct_by_type(struct_ty) return None -# ============================================================ -# lookup_field — 按结构体类型和字段名查找字段信息 -# ============================================================ def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr, field_name: str) -> FieldEntry | t.CPtr: - """按结构体类型和字段名查找字段信息 - - 两遍查找策略(跨模块同名类冲突的根本修复): - 第一遍: 类型指针 is 身份比较(最高优先级,类型唯一确定 entry) - 第二遍: 名称回退(is 未匹配时,按类名/strstr 匹配,字段未找到时 continue) - """ - if struct_ty is None or field_name is None or _struct_table is None: - return None - - # ============================================================ - # 两遍查找策略(跨模块同名类冲突的根本修复): - # - # 第一遍: 用类型指针 is 身份比较(最高优先级) - # - is 匹配唯一确定 entry,字段未找到直接返回 None - # - 规避联合类型 == BUG,且不受遍历顺序影响 - # - # 第二遍: 名称回退(is 未匹配到任何 entry 时才执行) - # - 用于未注册类型或 is 不可靠的场景 - # - 名称匹配但字段未找到时 continue(继续检查其他同名 entry) - # ============================================================ - - # 第一遍: is 身份比较(用 t.CUInt64T 指针值比较,避免 is 编译路径解引用悬空 Ty) - st_lk: t.CUInt64T = t.CUInt64T(struct_ty) - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - if t.CUInt64T(entry.Ty) == st_lk: - # is 匹配,查找字段 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - # is 匹配但字段未找到(类型唯一确定,无需继续) - return None - - # 第二遍: 名称回退(is 未匹配到) - ty_name: str = _extract_struct_name(struct_ty) - if ty_name is not None: - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - matched: int = 0 - if string.strcmp(entry.Name, ty_name) == 0: - matched = 1 - elif string.strstr(ty_name, entry.Name) is not None: - matched = 1 - if matched != 0: - # 查找字段 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - # 名称匹配但字段未找到,继续检查其他同名 entry(跨模块同名) - continue - # 所有条目都未匹配 + """按结构体类型和字段名查找字段信息(委托到 gen.lookup_field)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.lookup_field(struct_ty, field_name) return None -# ============================================================ -# lookup_field_by_class — 按类名和字段名查找字段信息 -# ============================================================ def lookup_field_by_class(class_name: str, field_name: str, sha1: str = None) -> FieldEntry | t.CPtr: - """按类名和字段名查找字段信息 - - 优先用 SHA1 匹配(跨模块同名类区分),无 SHA1 时按类名查找第一个 - """ - if class_name is None or field_name is None: - return None - - # 优先用 SHA1 匹配(跨模块同名类区分) - # 支持模块限定名:class_name 可能是 "HT.Translator",entry.Name 是 "Translator" - # 先精确匹配,失败后用 strrchr 提取类名部分回退匹配 - if sha1 is not None: - sha1_matched: int = 0 - # 计算类名回退部分("HT.Translator" → "Translator") - bare_name: str = class_name - dot_pos_lfbc: str = string.strrchr(class_name, '.') - if dot_pos_lfbc is not None: - bare_name = dot_pos_lfbc + 1 - if bare_name is None or bare_name[0] == '\0': - bare_name = class_name - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - # 精确匹配或类名回退匹配 - name_match: int = 0 - if string.strcmp(entry.Name, class_name) == 0: - name_match = 1 - elif bare_name is not class_name and string.strcmp(entry.Name, bare_name) == 0: - name_match = 1 - if name_match != 0: - if entry.ModuleSha1 is not None: - if string.strcmp(entry.ModuleSha1, sha1) == 0: - sha1_matched = 1 - # SHA1 + 类名匹配,查找字段 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - return None - - # 回退: 无 SHA1 或 SHA1 匹配失败,按类名查找第一个 - entry = find_struct(class_name) - if entry is None: - # 诊断:目标类未注册 - fb_lfbc: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_lfbc is not None: - viperlib.snprintf(fb_lfbc, 1024, - "lookup_field_by_class: 类 '%s' 未注册 (struct_count=%d)", - class_name, _struct_count) - VLogger.error(fb_lfbc, "STRUCT") - return None - # 诊断:找到结构体但字段未找到,打印字段表 - fb_fields: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_fields is not None: - viperlib.snprintf(fb_fields, 1024, - "lookup_field_by_class: 类 '%s' 已注册 (FieldCount=%d) 但字段 '%s' 未找到", - class_name, entry.FieldCount, field_name) - VLogger.error(fb_fields, "STRUCT") - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - fb_fn: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_fn is not None: - viperlib.snprintf(fb_fn, 1024, " 字段[%d]: %s", fi, fe.Name) - VLogger.error(fb_fn, "STRUCT") - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - # 诊断:找到结构体但字段未找到 + """按类名和字段名查找字段信息(委托到 gen.lookup_field_by_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.lookup_field_by_class(class_name, field_name, sha1) return None -# ============================================================ -# get_struct_type — 按类名获取结构体的 LLVM 类型 -# ============================================================ def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr: - """按类名获取结构体的 LLVM 类型""" - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is not None: - return entry.Ty + """按类名获取结构体的 LLVM 类型(委托到 gen.get_struct_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_struct_type(class_name) return None -# ============================================================ -# get_field_by_index — 按类名和字段索引获取字段信息 -# -# 用于构造函数 Point(10, 20) 按顺序访问字段 -# ============================================================ def get_field_by_index(class_name: str, idx: int) -> FieldEntry | t.CPtr: - """按类名和字段索引获取字段信息""" - if class_name is None: - return None - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return None - if idx < 0 or idx >= entry.FieldCount: - return None - return _get_field_entry(entry, idx) - - -# ============================================================ -# struct_has_defaults — 检查结构体是否有任何带默认值的字段 -# ============================================================ -def struct_has_defaults(class_name: str) -> int: - """检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无""" - if class_name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return 0 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.DefaultVal is not None: - return 1 - return 0 - - -# ============================================================ -# get_struct_type_from_value — 从 LLVM Value 的类型推断结构体类型 -# -# 如果 value 是 Ptr(Struct(...)),返回 Struct 类型 -# ============================================================ -def get_struct_type_from_value(val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr: - """从 Value 的类型推断结构体类型""" - if val is None or val.Ty is None: - return None - # 嵌套 match:先匹配 Ptr,再在 case 块内匹配 pointee 是否为 Struct - match val.Ty: - case llvmlite.LLVMType.Ptr(pointee): - match pointee: - case llvmlite.LLVMType.Struct(fields, fcount, name): - return pointee - case _: - return None - case _: - return None - - -# ============================================================ -# 联合体支持函数 -# ============================================================ - -# ============================================================ -# mark_as_union — 标记已注册的结构体为联合体 -# -# 联合体用 Struct([Array(Int8, max_size)]) 表示, -# 注册时用 register_struct 注册类型,再用此函数标记 IsUnion=1 -# ============================================================ -def mark_as_union(name: str) -> int: - """标记已注册的结构体为联合体,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.IsUnion = 1 - return 1 - - -# ============================================================ -# is_union_by_name — 按类名检查是否为联合体 -# ============================================================ -def is_union_by_name(name: str) -> int: - """按类名检查是否为联合体,返回 1=是 / 0=否""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.IsUnion - - -# ============================================================ -# is_union_by_type — 按类型指针检查是否为联合体 -# ============================================================ -def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int: - """按类型指针检查是否为联合体,返回 1=是 / 0=否 - - 先尝试类型指针 == 比较,失败时回退到名称匹配 - """ - if struct_ty is None or _struct_table is None: - return 0 - ty_name: str = _extract_struct_name(struct_ty) - st_iu: t.CUInt64T = t.CUInt64T(struct_ty) - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - matched: int = 0 - if t.CUInt64T(entry.Ty) == st_iu: - matched = 1 - elif ty_name is not None and entry.Name is not None: - if string.strcmp(entry.Name, ty_name) == 0: - matched = 1 - elif string.strstr(ty_name, entry.Name) is not None: - matched = 1 - if matched != 0: - return entry.IsUnion - return 0 - - -# ============================================================ -# OOP 支持函数 -# ============================================================ - -# ============================================================ -# mark_as_oop — 标记已注册的结构体为 OOP(有方法) -# ============================================================ -def mark_as_oop(name: str) -> int: - """标记已注册的结构体为 OOP,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.IsOOP = 1 - return 1 - - -# ============================================================ -# is_oop_by_name — 按类名检查是否为 OOP 结构体 -# ============================================================ -def is_oop_by_name(name: str) -> int: - """按类名检查是否为 OOP 结构体,返回 1=是 / 0=否""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.IsOOP - - -# ============================================================ -# mark_has_init — 标记结构体拥有 __init__ 方法 -# ============================================================ -def mark_has_init(name: str) -> int: - """标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.HasInit = 1 - return 1 - - -# ============================================================ -# has_init_by_name — 按类名检查是否有 __init__ 方法 -# ============================================================ -def has_init_by_name(name: str) -> int: - """按类名检查是否有 __init__ 方法,返回 1=有 / 0=无""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.HasInit - - -# ============================================================ -# mark_has_new — 标记结构体拥有 __new__ 方法 -# ============================================================ -def mark_has_new(name: str) -> int: - """标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.HasNew = 1 - return 1 - - -# ============================================================ -# has_new_by_name — 按类名检查是否有 __new__ 方法 -# ============================================================ -def has_new_by_name(name: str) -> int: - """按类名检查是否有 __new__ 方法,返回 1=有 / 0=无""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.HasNew - - -# ============================================================ -# get_class_name_by_type — 按 LLVM 类型指针查找类名 -# -# 用于方法调用:从变量类型 Ptr(Struct(...)) 反查类名, -# 以构造 ClassName.method_name 进行方法查找 -# ============================================================ -def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr) -> str: - """按类型指针查找类名,返回类名字符串或 None""" - if struct_ty is None or _struct_table is None: - return None - st_cn: t.CUInt64T = t.CUInt64T(struct_ty) - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - if t.CUInt64T(entry.Ty) == st_cn: - return entry.Name - # 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配 - # 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式) - ty_name: str = _extract_struct_name(struct_ty) - if ty_name is not None: - for j in range(_struct_count): - entry2: StructEntry | t.CPtr = _get_struct_entry(j) - if entry2 is not None and entry2.Name is not None: - # 构造 "SHA1.ClassName" 格式进行比较 - entry2_sha1: str = entry2.ModuleSha1 - if entry2_sha1 is not None: - full_nm: t.CChar | t.CPtr = pool.alloc(128) - if full_nm is not None: - viperlib.snprintf(full_nm, 128, "%s.%s", entry2_sha1, entry2.Name) - if string.strcmp(full_nm, ty_name) == 0: - return entry2.Name - # 也直接比较类名(struct_ty 的 Name 可能无 SHA1 前缀) - if string.strcmp(entry2.Name, ty_name) == 0: - return entry2.Name - # 最后回退: strstr 检查包含关系 - # ty_name 可能是 "SHA1.Counter",entry2.Name 是 "Counter" - if string.strstr(ty_name, entry2.Name) is not None: - return entry2.Name + """按类名和字段索引获取字段信息(委托到 gen.get_field_by_index)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_field_by_index(class_name, idx) + return None + + +def struct_has_defaults(class_name: str) -> int: + """检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无(委托到 gen.struct_has_defaults)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.struct_has_defaults(class_name) + return 0 + + +def get_struct_type_from_value(val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr: + """从 Value 的类型推断结构体类型(委托到 gen.get_struct_type_from_value)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_struct_type_from_value(val) + return None + + +def mark_as_union(name: str) -> int: + """标记已注册的结构体为联合体,返回 1=成功 / 0=失败(委托到 gen.mark_as_union)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.mark_as_union(name) + return 0 + + +def is_union_by_name(name: str) -> int: + """按类名检查是否为联合体,返回 1=是 / 0=否(委托到 gen.is_union_by_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_union_by_name(name) + return 0 + + +def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int: + """按类型指针检查是否为联合体,返回 1=是 / 0=否(委托到 gen.is_union_by_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_union_by_type(struct_ty) + return 0 + + +def mark_as_oop(name: str) -> int: + """标记已注册的结构体为 OOP,返回 1=成功 / 0=失败(委托到 gen.mark_as_oop)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.mark_as_oop(name) + return 0 + + +def is_oop_by_name(name: str) -> int: + """按类名检查是否为 OOP 结构体,返回 1=是 / 0=否(委托到 gen.is_oop_by_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_oop_by_name(name) + return 0 + + +def mark_has_init(name: str) -> int: + """标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败(委托到 gen.mark_has_init)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.mark_has_init(name) + return 0 + + +def has_init_by_name(name: str) -> int: + """按类名检查是否有 __init__ 方法,返回 1=有 / 0=无(委托到 gen.has_init_by_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.has_init_by_name(name) + return 0 + + +def mark_has_new(name: str) -> int: + """标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败(委托到 gen.mark_has_new)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.mark_has_new(name) + return 0 + + +def has_new_by_name(name: str) -> int: + """按类名检查是否有 __new__ 方法,返回 1=有 / 0=无(委托到 gen.has_new_by_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.has_new_by_name(name) + return 0 + + +def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr, + struct_ty: llvmlite.LLVMType | t.CPtr) -> str: + """按类型指针查找类名,返回类名字符串或 None(委托到 gen.get_class_name_by_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_class_name_by_type(pool, struct_ty) return None -# ============================================================ -# _extract_struct_name — 从 LLVMType 提取 Struct 变体的 Name 字段 -# ============================================================ def _extract_struct_name(ty: llvmlite.LLVMType | t.CPtr) -> str: - """从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct""" - if ty is None: - return None - match ty: - case llvmlite.LLVMType.Struct(fields, fcount, name): - return name - case _: - return None + """从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct(委托到 gen._extract_struct_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._extract_struct_name(ty) + return None -# ============================================================ -# VTable 支持函数 -# ============================================================ - -# ============================================================ -# mark_has_vtable — 标记结构体拥有虚表 -# ============================================================ def mark_has_vtable(name: str) -> int: - """标记结构体拥有虚表,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.HasVTable = 1 - return 1 + """标记结构体拥有虚表,返回 1=成功 / 0=失败(委托到 gen.mark_has_vtable)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.mark_has_vtable(name) + return 0 -# ============================================================ -# has_vtable_by_name — 按类名检查是否有虚表 -# ============================================================ def has_vtable_by_name(name: str) -> int: - """按类名检查是否有虚表,返回 1=有 / 0=无""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.HasVTable + """按类名检查是否有虚表,返回 1=有 / 0=无(委托到 gen.has_vtable_by_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.has_vtable_by_name(name) + return 0 -# ============================================================ -# mark_novtable — 标记结构体为 @t.NoVTable -# ============================================================ def mark_novtable(name: str) -> int: - """标记结构体为 NoVTable,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.IsNoVTable = 1 - return 1 + """标记结构体为 NoVTable,返回 1=成功 / 0=失败(委托到 gen.mark_novtable)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.mark_novtable(name) + return 0 -# ============================================================ -# is_novtable_by_name — 按类名检查是否为 NoVTable -# ============================================================ def is_novtable_by_name(name: str) -> int: - """按类名检查是否为 NoVTable,返回 1=是 / 0=否""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.IsNoVTable + """按类名检查是否为 NoVTable,返回 1=是 / 0=否(委托到 gen.is_novtable_by_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_novtable_by_name(name) + return 0 -# ============================================================ -# set_parent_name — 设置父类名 -# ============================================================ def set_parent_name(name: str, parent_name: str) -> int: - """设置结构体的父类名,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.ParentName = parent_name - return 1 + """设置结构体的父类名,返回 1=成功 / 0=失败(委托到 gen.set_parent_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.set_parent_name(name, parent_name) + return 0 -# ============================================================ -# set_parent_names — 设置多继承父类名数组 -# -# names_ptr: t.CSizeT 数组(每元素类名 str 指针),count 个。 -# 传 None/0 清除父类数组。ParentName(第一个父类)由调用方 -# 另行通过 set_parent_name 维护(兼容现有单继承调用方)。 -# ============================================================ def set_parent_names(name: str, names_ptr: t.CSizeT | t.CPtr, count: int) -> int: - """设置结构体的父类名数组(stdlib 深拷贝,跨文件永久存活)""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - if names_ptr is None or count <= 0: - entry.ParentNames = None - entry.ParentCount = 0 - return 1 - if count > PARENT_MAX: - count = PARENT_MAX - arr: t.CSizeT | t.CPtr = stdlib.malloc(8 * count) - if arr is None: - return 0 - for i in range(count): - addr: t.CSizeT = names_ptr[i] - arr[i] = 0 - if addr != 0: - src: str = (str | t.CPtr)(t.CVoid(addr, t.CPtr)) - if src is not None: - slen: t.CSizeT = string.strlen(src) - dup: t.CChar | t.CPtr = stdlib.malloc(slen + 1) - if dup is not None: - string.strcpy(dup, src) - arr[i] = t.CSizeT(dup) - entry.ParentNames = t.CSizeT(arr) - entry.ParentCount = count - return 1 + """设置结构体的父类名数组(stdlib 深拷贝,委托到 gen.set_parent_names)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.set_parent_names(name, names_ptr, count) + return 0 -# ============================================================ -# get_parent_count — 获取父类数量 -# ============================================================ def get_parent_count(name: str) -> int: - """获取父类数量(0=无父类,1=单继承,>1=多继承)""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.ParentCount + """获取父类数量(0=无父类,1=单继承,>1=多继承,委托到 gen.get_parent_count)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_parent_count(name) + return 0 -# ============================================================ -# get_parent_name_at — 获取第 idx 个父类名(声明顺序) -# ============================================================ def get_parent_name_at(name: str, idx: int) -> str: - """获取第 idx 个父类名,越界返回 None""" - if name is None or idx < 0: - return None - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None or entry.ParentNames is None: - return None - if idx >= entry.ParentCount: - return None - parr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.ParentNames, t.CPtr)) - addr: t.CSizeT = parr[idx] - if addr == 0: - return None - return (str | t.CPtr)(t.CVoid(addr, t.CPtr)) + """获取第 idx 个父类名,越界返回 None(委托到 gen.get_parent_name_at)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_parent_name_at(name, idx) + return None -# ============================================================ -# get_mro_chain — MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身) -# -# 返回: pool 分配的 t.CSizeT 数组(每元素类名 str 指针),末尾 0 结束。 -# 顺序: 自身 → 父类1 及祖先 → 父类2 及祖先(先声明优先,菱形去重)。 -# 失败返回 None。 -# ============================================================ def get_mro_chain(pool: memhub.MemBuddy | t.CPtr, name: str) -> t.CSizeT | t.CPtr: - """MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身)""" - if pool is None or name is None: - return None - arr: t.CSizeT | t.CPtr = pool.alloc(8 * (MRO_MAX + 1)) - if arr is None: - return None - stack: t.CSizeT | t.CPtr = pool.alloc(8 * MRO_MAX) - if stack is None: - return None - visited: t.CSizeT | t.CPtr = pool.alloc(8 * MRO_MAX) - if visited is None: - return None - stack_count: int = 0 - out_count: int = 0 - visit_count: int = 0 - # 初始压入自身 - stack[0] = t.CSizeT(name) - stack_count = 1 - while stack_count > 0: - stack_count -= 1 - cur_addr: t.CSizeT = stack[stack_count] - cur: str = (str | t.CPtr)(t.CVoid(cur_addr, t.CPtr)) - if cur is None: - continue - # 已访问检查(线性搜索) - dup: int = 0 - for vi in range(visit_count): - va: t.CSizeT = visited[vi] - if va != 0: - vn: str = (str | t.CPtr)(t.CVoid(va, t.CPtr)) - if vn is not None and string.strcmp(vn, cur) == 0: - dup = 1 - break - if dup != 0: - continue - # 加入结果与已访问集合 - if out_count < MRO_MAX: - arr[out_count] = t.CSizeT(cur) - out_count += 1 - if visit_count < MRO_MAX: - visited[visit_count] = t.CSizeT(cur) - visit_count += 1 - # 父类逆序压栈(正向 range 计算逆序索引,保证声明顺序弹出) - entry: StructEntry | t.CPtr = find_struct(cur) - if entry is not None and entry.ParentCount > 0 and entry.ParentNames is not None: - pc: int = entry.ParentCount - parr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.ParentNames, t.CPtr)) - for pi2 in range(pc): - pi: int = pc - 1 - pi2 - if stack_count < MRO_MAX: - stack[stack_count] = parr[pi] - stack_count += 1 - # 末尾 0 结束 - arr[out_count] = 0 - return arr + """MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身,委托到 gen.get_mro_chain)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_mro_chain(pool, name) + return None -# ============================================================ -# get_parent_name — 获取父类名 -# ============================================================ def get_parent_name(name: str) -> str: - """获取结构体的父类名,返回 None=无父类""" - if name is None: - return None - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return None - return entry.ParentName + """获取结构体的父类名,返回 None=无父类(委托到 gen.get_parent_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_parent_name(name) + return None -# ============================================================ -# set_vtable_methods — 设置虚表方法名数组 -# -# methods 是一个 str 数组(每个元素是方法名字符串指针), -# count 是方法数量。数组直接引用,不复制。 -# ============================================================ def set_vtable_methods(name: str, methods: t.CChar | t.CPtr, count: int) -> int: - """设置虚表方法名数组,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.VTableMethods = methods - entry.VTableMethodCount = count - return 1 + """设置虚表方法名数组,返回 1=成功 / 0=失败(委托到 gen.set_vtable_methods)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.set_vtable_methods(name, methods, count) + return 0 -# ============================================================ -# get_vtable_method_index — 获取方法在虚表中的索引 -# -# 在 VTableMethods 数组中查找方法名,返回索引(-1=未找到) -# ============================================================ def get_vtable_method_index(name: str, method_name: str) -> int: - """获取方法在虚表中的索引,返回 -1=未找到""" - if name is None or method_name is None: - return -1 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None or entry.VTableMethods is None: - return -1 - # VTableMethods 字段声明为 t.CChar*,但实际存储的是 t.CSizeT 数组 - # 必须转换为 t.CSizeT* 才能正确读取 8 字节指针值 - methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr)) - for i in range(entry.VTableMethodCount): - mname_addr: t.CSizeT = methods_arr[i] - if mname_addr == 0: - continue - mname: str = (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) - if mname is not None and string.strcmp(mname, method_name) == 0: - return i - return -1 + """获取方法在虚表中的索引,返回 -1=未找到(委托到 gen.get_vtable_method_index)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_vtable_method_index(name, method_name) + return 0 -# ============================================================ -# get_vtable_method_count — 获取虚表方法数量 -# ============================================================ def get_vtable_method_count(name: str) -> int: - """获取虚表方法数量""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.VTableMethodCount + """获取虚表方法数量(委托到 gen.get_vtable_method_count)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_vtable_method_count(name) + return 0 -# ============================================================ -# get_vtable_method_name — 获取虚表中第 idx 个方法名 -# -# 返回方法名字符串指针,None=越界或未设置 -# ============================================================ def get_vtable_method_name(name: str, idx: int) -> str: - """获取虚表中第 idx 个方法名,返回 None=越界""" - if name is None or idx < 0: - return None - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None or entry.VTableMethods is None: - return None - if idx >= entry.VTableMethodCount: - return None - methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr)) - mname_addr: t.CSizeT = methods_arr[idx] - if mname_addr == 0: - return None - return (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) + """获取虚表中第 idx 个方法名,返回 None=越界(委托到 gen.get_vtable_method_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_vtable_method_name(name, idx) + return None -# ============================================================ -# get_field_count — 获取结构体字段数量(访问器,绕过 stub 类型限制) -# ============================================================ def get_field_count(name: str) -> int: - """获取结构体字段数量,返回 -1=未找到""" - if name is None: - return -1 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return -1 - return entry.FieldCount + """获取结构体字段数量,返回 -1=未找到(委托到 gen.get_field_count)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_field_count(name) + return 0 -# ============================================================ -# ensure_struct_def_in_module — 确保跨模块结构体的完整定义在当前模块中可用 -# -# 当局部变量声明为值类型(如 f: File)时,alloca 需要完整类型定义。 -# 如果结构体定义在另一个模块(名称含 SHA1 前缀,如 "0035c95a18d4f8e8.File"), -# 将其完整定义复制到当前模块。module_add_named_type 会用完整定义替换 -# 已存在的 opaque 声明,使 alloca 能正确分配空间。 -# -# Args: -# pool: 内存池 -# mod: 当前 LLVM 模块 -# ty: 变量类型(Struct/Ptr/其他) -# ============================================================ def ensure_struct_def_in_module(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - ty: llvmlite.LLVMType | t.CPtr): - """确保跨模块结构体的完整定义在当前模块中可用(供 alloca 使用) - - 处理两种情况: - 1. Struct 值类型:需要完整定义(供 alloca 分配空间) - 2. Ptr(Struct) 指针类型:需要 pointee 至少有 opaque 声明 - """ - if ty is None or mod is None or pool is None: - return - # 指针类型:确保 pointee 至少有 opaque 声明 - match ty: - case llvmlite.LLVMType.Ptr(pointee): - llvmlite.module_ensure_opaque_for_type(mod, pool, ty) - # 如果 pointee 是 Struct,递归复制完整定义 - # (GEP 访问字段需要 sized 类型,仅 opaque 会导致 llc 报错) - if pointee is not None: - ensure_struct_def_in_module(pool, mod, pointee) - return - case _: - pass - # 获取结构体名称(非 Struct 类型返回 None) - sname: t.CChar | t.CPtr = llvmlite.get_struct_name(ty) - if sname is None: - return - # 检查是否为跨模块引用(名称包含 '.') - if string.strchr(sname, 46) is None: - return # 非跨模块引用,无需处理 - # 提取类名(第一个 '.' 之后的部分) - # 必须用 strchr 而非 strrchr:泛型特化名如 "list[ast.AST|t.CPtr]" - # 内部含 '.'(ast.AST),strrchr 会错误地把类名解析为 "AST|t.CPtr]" - dot_pos: str = string.strchr(sname, '.') - if dot_pos is None: - return - class_name: str = dot_pos + 1 - if class_name is None or class_name[0] == '\0': - return - # 提取 SHA1(sname 到 dot_pos 之间,用 strlen 避免指针减法) - total_len: t.CSizeT = string.strlen(sname) - class_name_len: t.CSizeT = string.strlen(class_name) - sha1_len: t.CSizeT = total_len - class_name_len - 1 - sha1_buf: t.CChar | t.CPtr = pool.alloc(32) - if sha1_buf is None: - return - string.strncpy(sha1_buf, sname, sha1_len) - sha1_buf[sha1_len] = '\0' - # 按类名 + SHA1 查找结构体定义 - entry: StructEntry | t.CPtr = find_struct_by_module(class_name, sha1_buf) - if entry is None: - # 回退到按类名查找(可能找到不同模块的同名类,但总比没有好) - entry = find_struct(class_name) - if entry is None: - return - if entry.Ty is None: - return - # 将完整定义添加到当前模块(会替换已存在的 opaque 声明) - llvmlite.module_add_named_type(mod, pool, entry.Ty) - # 递归扫描字段类型,确保值类型子结构体(如 WIN32_FIND_DATAA 中的 FILETIME) - # 也有完整定义。指针类型字段只需 opaque 声明(已由 module_ensure_opaque_for_type 处理)。 - _ensure_field_types_in_module(pool, mod, entry.Ty) + mod: llvmlite.LLVMModule | t.CPtr, + ty: llvmlite.LLVMType | t.CPtr): + """确保跨模块结构体的完整定义在当前模块中可用(委托到 gen.ensure_struct_def_in_module)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.ensure_struct_def_in_module(pool, mod, ty) -# ============================================================ -# _ensure_field_types_in_module - 递归扫描结构体字段类型 -# -# 遍历 Struct 的 Fields 链表,对每个值类型子结构体调用 -# ensure_struct_def_in_module。指针/数组/基本类型递归到 pointee/element。 -# ============================================================ def _ensure_field_types_in_module(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - ty: llvmlite.LLVMType | t.CPtr): - """递归扫描类型树,确保值类型子结构体有完整定义""" - if ty is None or mod is None or pool is None: - return - # 嵌套 match 遍历类型树 - match ty: - case llvmlite.LLVMType.Struct(fields, fcount, sname): - # 遍历字段链表 - if fields is not None: - fld: llvmlite.ParamNode | t.CPtr = fields - while fld is not None: - if fld.Ty is not None: - # 值类型子结构体(如 FILETIME)需要完整定义 - match fld.Ty: - case llvmlite.LLVMType.Struct(f2, fc2, n2): - ensure_struct_def_in_module(pool, mod, fld.Ty) - case _: - pass - _ensure_field_types_in_module(pool, mod, fld.Ty) - fld = fld.Next - case llvmlite.LLVMType.Ptr(pointee): - # 指针类型:pointee 只需 opaque 声明,不需要完整定义 - # 但如果 pointee 是 Struct,确保 opaque 声明存在 - if pointee is not None: - llvmlite.module_ensure_opaque_for_type(mod, pool, ty) - case llvmlite.LLVMType.Array(elem_ty, acount): - # 数组类型:元素如果是值类型结构体,需要完整定义 - if elem_ty is not None: - _ensure_field_types_in_module(pool, mod, elem_ty) - case _: - pass + mod: llvmlite.LLVMModule | t.CPtr, + ty: llvmlite.LLVMType | t.CPtr): + """递归扫描类型树,确保值类型子结构体有完整定义(委托到 gen._ensure_field_types_in_module)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._ensure_field_types_in_module(pool, mod, ty) -# ============================================================ -# get_field_name_ptr — 获取 FieldEntry 的字段名指针(访问器) -# ============================================================ def get_field_name_ptr(fe: FieldEntry | t.CPtr) -> str: - """获取 FieldEntry 的字段名,返回 None=未设置""" - if fe is None: - return None - return fe.Name + """获取 FieldEntry 的字段名,返回 None=未设置(委托到 gen.get_field_name_ptr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_field_name_ptr(fe) + return None -# ============================================================ -# get_field_type_ptr — 获取 FieldEntry 的字段类型指针(访问器) -# ============================================================ def get_field_type_ptr(fe: FieldEntry | t.CPtr) -> llvmlite.LLVMType | t.CPtr: - """获取 FieldEntry 的字段类型,返回 None=未设置""" - if fe is None: - return None - return fe.Ty + """获取 FieldEntry 的字段类型,返回 None=未设置(委托到 gen.get_field_type_ptr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_field_type_ptr(fe) + return None -# ============================================================ -# get_field_default_ptr — 获取 FieldEntry 的默认值 AST 指针(访问器) -# ============================================================ def get_field_default_ptr(fe: FieldEntry | t.CPtr) -> ast.AST | t.CPtr: - """获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值""" - if fe is None: - return None - return fe.DefaultVal + """获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值(委托到 gen.get_field_default_ptr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_field_default_ptr(fe) + return None -# ============================================================ -# get_field_annot_class_name — 获取 FieldEntry 的注解类名(访问器) -# ============================================================ def get_field_annot_class_name(fe: FieldEntry | t.CPtr) -> str: - """获取 FieldEntry 的原始类型注解类名,返回 None=未设置""" - if fe is None: - return None - return fe.AnnotClassName + """获取 FieldEntry 的原始类型注解类名,返回 None=未设置(委托到 gen.get_field_annot_class_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_field_annot_class_name(fe) + return None diff --git a/App/main.vp b/App/main.vp index 4802287..b581a34 100644 --- a/App/main.vp +++ b/App/main.vp @@ -87,8 +87,9 @@ def main() -> int: gen.__before_init__() gen.__init__(mb) GenGenerator.set_global_gen(gen) - # P2: 注入 HandlesType 模块级单例(Phase1 阶段即调用 HandlesType 状态函数) + # P2: 注入 HandlesType/HandlesStruct 模块级单例(Phase1 阶段即调用其状态函数) HandlesType.set_global_gen(gen) + HandlesStruct.set_global_gen(gen) # 初始化 VLogger 并打印启动日志 log: VLogger.Logger | t.CPtr = VLogger.get_logger()