snapshot before regression test

This commit is contained in:
t
2026-07-18 19:25:40 +08:00
commit 796222a300
2295 changed files with 206453 additions and 0 deletions

View File

@@ -0,0 +1,975 @@
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 # 虚表方法名数组(每个方法名 strVTableMethodCount 个)
ModuleSha1: t.CChar | t.CPtr # 定义该类的模块 SHA1None=无 SHA1
# ============================================================
# 全局注册表(静态分配)
# ============================================================
_struct_table: StructEntry | t.CPtr = None
_struct_count: int = 0
# ============================================================
# 跨模块命名空间隔离per-file 结构体可见性
#
# _visible_structs: 当前文件可见的结构体名HashTableO(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