import t, c from stdint import * import memhub import string import llvmlite import stdio import ast import hashtable # ============================================================ # HandlesStruct - 结构体类型注册和字段查找 # # 管理 class 定义的结构体类型信息: # - 类名 → LLVM StructType # - 字段名 → 字段索引和类型 # # 使用全局数组存储,线性查找(结构体数量通常很少) # ============================================================ STRUCT_MAX: t.CDefine = 512 FIELD_MAX: t.CDefine = 32 FIELD_NAME_MAX: t.CDefine = 64 # ============================================================ # FieldEntry - 字段信息条目 # ============================================================ @t.NoVTable class FieldEntry: Name: t.CChar | t.CPtr # 字段名(字符串) Index: int # 字段在结构体中的索引 Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型 DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值) AnnotClassName: t.CChar | t.CPtr # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型) # ============================================================ # StructEntry - 结构体注册条目 # ============================================================ @t.NoVTable class StructEntry: Name: t.CChar | t.CPtr # 类名 Ty: llvmlite.LLVMType | t.CPtr # LLVM StructType FieldCount: int # 字段数量 Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位) IsUnion: int # 1=联合体 / 0=普通结构体 IsOOP: int # 1=OOP结构体(有方法) / 0=纯内存结构体 HasInit: int # 1=有__init__方法 / 0=无 HasNew: int # 1=有__new__方法 / 0=无 HasVTable: int # 1=有虚表 / 0=无虚表 IsNoVTable: int # 1=明确标记 @t.NoVTable / 0=未标记 ParentName: t.CChar | t.CPtr # 父类名(None=无父类) VTableMethodCount: int # 虚表中的方法数量 VTableMethods: t.CChar | t.CPtr # 虚表方法名数组(每个方法名 str,VTableMethodCount 个) ModuleSha1: t.CChar | t.CPtr # 定义该类的模块 SHA1(None=无 SHA1) # ============================================================ # 全局注册表(静态分配) # ============================================================ _struct_table: StructEntry | t.CPtr = None _struct_count: int = 0 # ============================================================ # 跨模块命名空间隔离: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 # ============================================================ # 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) # ============================================================ # 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) # ============================================================ # 初始化结构体注册表 # ============================================================ def init_struct_table(pool: memhub.MemBuddy | t.CPtr) -> int: """初始化结构体注册表,返回 1 成功""" global _struct_table global _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 # ============================================================ # _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)) # ============================================================ # _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)) # ============================================================ # 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: """注册结构体类型,返回 StructEntry 指针 用类型指针去重(is 比较),不用类名去重。 这样跨模块同名类可以共存,各自有独立的字段定义。 sha1 参数在注册时直接设置 ModuleSha1(避免 set_struct_sha1 找错 entry)。 """ if init_struct_table(pool) == 0: return None # 用类型指针去重(同一类型不重复注册,支持跨模块同名类) 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 existing.Ty is struct_ty: return existing if _struct_count >= STRUCT_MAX: stdio.printf("[STRUCT] table full, cannot register %s\n", name) return None entry: StructEntry | t.CPtr = _get_struct_entry(_struct_count) if entry is None: return None # 分配字段数组 field_size: t.CSizeT = FieldEntry.__sizeof__() entry.Fields = pool.alloc(field_size * FIELD_MAX) if entry.Fields is None: return None string.memset(entry.Fields, 0, field_size * FIELD_MAX) # 复制类名 name_len: t.CSizeT = string.strlen(name) 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) 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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: stdio.printf("[STRUCT] field table full for %s\n", struct_entry.Name) return -1 idx: int = struct_entry.FieldCount fe: FieldEntry | t.CPtr = _get_field_entry(struct_entry, idx) if fe is None: return -1 # 复制字段名 name_len: t.CSizeT = string.strlen(field_name) 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 # ============================================================ # find_struct — 按类名查找结构体 # ============================================================ def find_struct(name: str) -> StructEntry | t.CPtr: """按类名查找结构体,返回 StructEntry 或 None""" 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 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: """按类型指针查找结构体(is 比较),返回 StructEntry 或 None""" if struct_ty 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.Ty is not None: if entry.Ty is struct_ty: return entry 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 身份比较 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 entry.Ty is struct_ty: # 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 # 所有条目都未匹配 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 匹配(跨模块同名类区分) if sha1 is not None: sha1_matched: int = 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: 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: return None 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 # ============================================================ # 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 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 _is_struct_type(ty: llvmlite.LLVMType | t.CPtr) -> int: """检查 ty 是否是 Struct 类型(独立函数,规避嵌套 match 编译器 BUG)""" if ty is None: return 0 match ty: case llvmlite.LLVMType.Struct(fields, fcount, name): return 1 case _: return 0 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 val.Ty: case llvmlite.LLVMType.Ptr(pointee): if _is_struct_type(pointee) != 0: return pointee 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) 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 entry.Ty is struct_ty: 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 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 entry.Ty is struct_ty: 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 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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)) # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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 # ============================================================ # 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