976 lines
38 KiB
Python
976 lines
38 KiB
Python
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
|