1210 lines
49 KiB
Python
1210 lines
49 KiB
Python
import t, c
|
||
from stdint import *
|
||
import memhub
|
||
import string
|
||
import llvmlite
|
||
import stdio
|
||
import ast
|
||
import hashtable
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
|
||
|
||
# ============================================================
|
||
# HandlesStruct - 结构体类型注册和字段查找
|
||
#
|
||
# 管理 class 定义的结构体类型信息:
|
||
# - 类名 → LLVM StructType
|
||
# - 字段名 → 字段索引和类型
|
||
#
|
||
# 使用全局数组存储,线性查找(结构体数量通常很少)
|
||
# ============================================================
|
||
|
||
STRUCT_MAX: t.CDefine = 512
|
||
FIELD_MAX: t.CDefine = 48
|
||
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:
|
||
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
|
||
|
||
# 分配字段数组
|
||
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:
|
||
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
|
||
|
||
# 复制字段名
|
||
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
|
||
|
||
|
||
# ============================================================
|
||
# get_struct_count — 获取已注册结构体数量(供 Phase2 多遍预注册判断收敛)
|
||
# ============================================================
|
||
def get_struct_count() -> int:
|
||
"""返回当前已注册的结构体数量"""
|
||
return _struct_count
|
||
|
||
|
||
# ============================================================
|
||
# 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
|
||
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 匹配(跨模块同名类区分)
|
||
# 支持模块限定名: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:
|
||
# 诊断:遍历打印所有已注册结构体名,确认目标类是否在注册表中
|
||
stdio.printf("[LFBC-DIAG] FAIL class=%s field=%s sha1=%s count=%d\n",
|
||
class_name, field_name,
|
||
sha1 if sha1 is not None else "(null)", _struct_count)
|
||
for diag_i in range(_struct_count):
|
||
diag_entry: StructEntry | t.CPtr = _get_struct_entry(diag_i)
|
||
if diag_entry is not None and diag_entry.Name is not None:
|
||
stdio.printf("[LFBC-DIAG] [%d] %s sha1=%s fc=%d\n",
|
||
diag_i, diag_entry.Name,
|
||
diag_entry.ModuleSha1 if diag_entry.ModuleSha1 is not None else "(null)",
|
||
diag_entry.FieldCount)
|
||
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
|
||
# 诊断:找到结构体但字段未找到
|
||
stdio.printf("[LFBC-DIAG] NOFIELD class=%s field=%s sname=%s fc=%d\n",
|
||
class_name, field_name, entry.Name, entry.FieldCount)
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# find_subclass_with_field — 在基类的所有子类中搜索包含指定字段的结构体
|
||
#
|
||
# 用于处理 "注解类型是基类但实际值是派生类" 的场景:
|
||
# node: AST | t.CPtr = If(...)
|
||
# node.orelse = orelse ← orelse 在 If 上,不在 AST 上
|
||
#
|
||
# 遍历所有已注册结构体,通过 ParentName 链检查继承关系,
|
||
# 返回第一个包含 field_name 的子类 StructEntry。
|
||
# ============================================================
|
||
def find_subclass_with_field(base_class_name: str,
|
||
field_name: str) -> StructEntry | t.CPtr:
|
||
"""在 base_class_name 的所有子类中搜索包含 field_name 的结构体
|
||
|
||
返回第一个找到的 StructEntry(包含正确的 Ty),None=未找到
|
||
"""
|
||
if base_class_name is None or field_name is None:
|
||
return None
|
||
sc_i: int
|
||
for sc_i in range(_struct_count):
|
||
sc_entry: StructEntry | t.CPtr = _get_struct_entry(sc_i)
|
||
if sc_entry is None or sc_entry.Name is None:
|
||
continue
|
||
# 检查 sc_entry 是否是 base_class_name 的子类(传递性)
|
||
cur_parent: str = get_parent_name(sc_entry.Name)
|
||
while cur_parent is not None:
|
||
if string.strcmp(cur_parent, base_class_name) == 0:
|
||
# 是子类,检查是否有该字段
|
||
sc_fi: int
|
||
for sc_fi in range(sc_entry.FieldCount):
|
||
sc_fe: FieldEntry | t.CPtr = _get_field_entry(sc_entry, sc_fi)
|
||
if sc_fe is not None and sc_fe.Name is not None:
|
||
if string.strcmp(sc_fe.Name, field_name) == 0:
|
||
return sc_entry
|
||
break
|
||
cur_parent = get_parent_name(cur_parent)
|
||
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 _is_ptr_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||
"""检查 ty 是否是 Ptr 类型(独立函数,规避嵌套 match 编译器 BUG)"""
|
||
if ty is None:
|
||
return 0
|
||
match ty:
|
||
case llvmlite.LLVMType.Ptr(pointee):
|
||
return 1
|
||
case _:
|
||
return 0
|
||
|
||
|
||
def _get_ptr_pointee(ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||
"""获取 Ptr 类型的 pointee(独立函数,规避嵌套 match 编译器 BUG)"""
|
||
if ty is None:
|
||
return None
|
||
match ty:
|
||
case llvmlite.LLVMType.Ptr(pointee):
|
||
return pointee
|
||
case _:
|
||
return None
|
||
|
||
|
||
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
|
||
|
||
|
||
# ============================================================
|
||
# 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 声明
|
||
# 用 _is_ptr_type 检查(独立函数,规避嵌套 match BUG)
|
||
if _is_ptr_type(ty) != 0:
|
||
llvmlite.module_ensure_opaque_for_type(mod, pool, ty)
|
||
# 如果 pointee 是 Struct,递归复制完整定义
|
||
# (GEP 访问字段需要 sized 类型,仅 opaque 会导致 llc 报错)
|
||
pointee: llvmlite.LLVMType | t.CPtr = _get_ptr_pointee(ty)
|
||
if pointee is not None:
|
||
ensure_struct_def_in_module(pool, mod, pointee)
|
||
return
|
||
# 获取结构体名称(非 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)
|
||
|
||
|
||
# ============================================================
|
||
# _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 BUG)
|
||
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)需要完整定义
|
||
if _is_struct_type(fld.Ty) != 0:
|
||
ensure_struct_def_in_module(pool, mod, fld.Ty)
|
||
_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
|
||
|
||
|
||
# ============================================================
|
||
# 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
|