3335 lines
136 KiB
Python
3335 lines
136 KiB
Python
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||
|
||
|
||
# 枚举成员临时数组最大数量(本地常量)
|
||
ENUM_MEMBER_MAX_LOCAL: t.CDefine = 64
|
||
|
||
# REnum 变体表容量上限(本地常量)
|
||
RENUM_CLASS_MAX: t.CDefine = 64
|
||
|
||
# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug)
|
||
SCOPE_FUNCTION: t.CDefine = 1
|
||
RENUM_VARIANT_PER_CLASS: t.CDefine = 32
|
||
RENUM_FIELD_PER_VARIANT: t.CDefine = 16
|
||
|
||
|
||
# ============================================================
|
||
# HandlesClassDef - class 定义处理
|
||
#
|
||
# 解析 class 定义,创建 LLVM StructType 并注册字段信息
|
||
#
|
||
# 纯内存结构体(无方法)的 class 定义:
|
||
# class Point:
|
||
# x: t.CInt
|
||
# y: t.CInt
|
||
#
|
||
# 生成 LLVM 类型: { i32, i32 }
|
||
# 注册字段: x→index 0, y→index 1
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# _is_cenum_base — 检查 base 节点是否为 t.CEnum
|
||
#
|
||
# 支持 Name(id='CEnum') 和 Attribute(value=Name('t'), attr='CEnum')
|
||
# ============================================================
|
||
def _is_cenum_base(base_node: ast.AST | t.CPtr) -> int:
|
||
"""检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否"""
|
||
if base_node is None:
|
||
return 0
|
||
k: int = base_node.kind()
|
||
# Name('CEnum') 形式(from t import CEnum)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
|
||
if nm.id is not None and string.strcmp(nm.id, "CEnum") == 0:
|
||
return 1
|
||
return 0
|
||
# Attribute(t.CEnum) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
|
||
if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _is_enum_class — 检查 ClassDef 是否继承自 t.CEnum
|
||
# ============================================================
|
||
def _is_enum_class(cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查 ClassDef 是否继承自 t.CEnum,返回 1=是 / 0=否"""
|
||
if cd is None or cd.bases is None:
|
||
return 0
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = bases.__len__()
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
if _is_cenum_base(base_node) == 1:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _is_cunion_base — 检查 base 节点是否为 t.CUnion
|
||
#
|
||
# 支持 Name(id='CUnion') 和 Attribute(value=Name('t'), attr='CUnion')
|
||
# ============================================================
|
||
def _is_cunion_base(base_node: ast.AST | t.CPtr) -> int:
|
||
"""检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否"""
|
||
if base_node is None:
|
||
return 0
|
||
k: int = base_node.kind()
|
||
# Name('CUnion') 形式(from t import CUnion)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
|
||
if nm.id is not None and string.strcmp(nm.id, "CUnion") == 0:
|
||
return 1
|
||
return 0
|
||
# Attribute(t.CUnion) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
|
||
if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _is_union_class — 检查 ClassDef 是否继承自 t.CUnion
|
||
# ============================================================
|
||
def _is_union_class(cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查 ClassDef 是否继承自 t.CUnion,返回 1=是 / 0=否"""
|
||
if cd is None or cd.bases is None:
|
||
return 0
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = bases.__len__()
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
if _is_cunion_base(base_node) == 1:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _is_crenum_base — 检查 base 节点是否为 t.REnum
|
||
#
|
||
# 支持 Name(id='REnum') 和 Attribute(value=Name('t'), attr='REnum')
|
||
# ============================================================
|
||
def _is_crenum_base(base_node: ast.AST | t.CPtr) -> int:
|
||
"""检查 base 节点是否为 t.REnum,返回 1=是 / 0=否"""
|
||
if base_node is None:
|
||
return 0
|
||
k: int = base_node.kind()
|
||
# Name('REnum') 形式(from t import REnum)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
|
||
if nm.id is not None and string.strcmp(nm.id, "REnum") == 0:
|
||
return 1
|
||
return 0
|
||
# Attribute(t.REnum) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
|
||
if at.attr is not None and string.strcmp(at.attr, "REnum") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _is_renum_class — 检查 ClassDef 是否继承自 t.REnum
|
||
# ============================================================
|
||
def _is_renum_class(cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查 ClassDef 是否继承自 t.REnum,返回 1=是 / 0=否"""
|
||
if cd is None or cd.bases is None:
|
||
return 0
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = bases.__len__()
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
if _is_crenum_base(base_node) == 1:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# VTable 装饰器检测和继承关系判断
|
||
# ============================================================
|
||
|
||
# 标记基类集合(非真实父类,仅作为类型标记)
|
||
_MARKER_BASES: t.CDefine = 8
|
||
# 使用字符串比较代替集合,标记基类列表
|
||
# Object, CVTable, Exception, CEnum, Enum, CStruct, CUnion, REnum
|
||
|
||
|
||
# ============================================================
|
||
# _has_decorator — 检查 ClassDef/FunctionDef 的 decorator_list 中是否有指定装饰器
|
||
#
|
||
# 支持 @t.Name 和 @Name 两种形式
|
||
# 返回 1=有 / 0=无
|
||
# ============================================================
|
||
def _has_decorator(decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||
deco_name: str) -> int:
|
||
"""检查 decorator_list 中是否有指定装饰器名"""
|
||
if decorator_list is None:
|
||
return 0
|
||
dn: t.CSizeT = decorator_list.__len__()
|
||
if dn == 0:
|
||
return 0
|
||
for di in range(dn):
|
||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
k: int = deco.kind()
|
||
# @t.NoVTable 形式(Attribute)
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco)
|
||
if at.attr is not None and string.strcmp(at.attr, deco_name) == 0:
|
||
# 检查 value 是 Name('t')
|
||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||
vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||
if vn.id is not None and string.strcmp(vn.id, "t") == 0:
|
||
return 1
|
||
return 0
|
||
# @NoVTable 形式(Name,from t import NoVTable)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco)
|
||
if nm.id is not None and string.strcmp(nm.id, deco_name) == 0:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _is_marker_base — 检查基类名是否为标记基类(非真实父类)
|
||
#
|
||
# 标记基类: Object, CVTable, Exception, CEnum, Enum, CStruct, CUnion, REnum
|
||
# ============================================================
|
||
def _is_marker_base(base_name: str) -> int:
|
||
"""检查基类名是否为标记基类,返回 1=是 / 0=否"""
|
||
if base_name is None:
|
||
return 0
|
||
if string.strcmp(base_name, "Object") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CVTable") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "Exception") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CEnum") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "Enum") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CStruct") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CUnion") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "REnum") == 0:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _get_base_name — 从 base AST 节点提取基类名
|
||
#
|
||
# 支持 Name(id), Attribute(attr), Subscript(value, slice)
|
||
# 对于 Subscript(如 GSListNode[Value]),需要 pool 拼接特化名 "GSListNode[Value]"
|
||
# ============================================================
|
||
def _get_base_name(base_node: ast.AST | t.CPtr,
|
||
pool: memhub.MemBuddy | t.CPtr = None) -> str:
|
||
"""从 base AST 节点提取基类名,返回 None=失败
|
||
|
||
对于 Subscript 节点,需要 pool 分配内存拼接特化名;
|
||
pool=None 时降级返回基类名(不含类型实参)
|
||
"""
|
||
if base_node is None:
|
||
return None
|
||
k: int = base_node.kind()
|
||
# Name(id) 形式
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
|
||
return nm.id
|
||
# Attribute(attr) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
|
||
return at.attr
|
||
# Subscript(value, slice) 形式 — 如 GSListNode[Value]
|
||
if k == ast.ASTKind.Subscript:
|
||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node)
|
||
if sub is None or sub.value is None or sub.slice is None:
|
||
return None
|
||
# 提取基类名(如 "GSListNode")
|
||
base_nm: str = _get_base_name(sub.value, pool)
|
||
if base_nm is None:
|
||
return None
|
||
# 提取类型实参名(如 "Value")
|
||
slice_k: int = sub.slice.kind()
|
||
arg_nm: str = None
|
||
if slice_k == ast.ASTKind.Name:
|
||
sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice)
|
||
arg_nm = sl_nm.id
|
||
# 如果无法提取类型实参,返回基类名(降级)
|
||
if arg_nm is None:
|
||
return base_nm
|
||
# 无 pool 时返回基类名(降级,无法拼接特化名)
|
||
if pool is None:
|
||
return base_nm
|
||
# 拼接特化名 "GSListNode[Value]"
|
||
base_len: t.CSizeT = string.strlen(base_nm)
|
||
arg_len: t.CSizeT = string.strlen(arg_nm)
|
||
total_len: t.CSizeT = base_len + arg_len + 3 # "[" + arg + "]" + NUL
|
||
mangled: str = pool.alloc(total_len)
|
||
if mangled is None:
|
||
return base_nm # 降级
|
||
mangled[0] = '\0'
|
||
string.strcat(mangled, base_nm)
|
||
string.strcat(mangled, "[")
|
||
string.strcat(mangled, arg_nm)
|
||
string.strcat(mangled, "]")
|
||
return mangled
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# _get_parent_class — 获取 ClassDef 的真实父类名(非标记基类)
|
||
#
|
||
# 遍历 bases,返回第一个非标记基类的名字,None=无真实父类
|
||
# 支持 Name, Attribute, Subscript 三种 base 节点
|
||
# 对于 Subscript(如 GSListNode[Value]),需要 trans.Pool 拼接特化名
|
||
# ============================================================
|
||
def _get_parent_class(cd: ast.ClassDef | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = None) -> str:
|
||
"""获取 ClassDef 的真实父类名,返回 None=无真实父类"""
|
||
if cd is None or cd.bases is None:
|
||
return None
|
||
pool: memhub.MemBuddy | t.CPtr = None
|
||
if trans is not None:
|
||
pool = trans.Pool
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = bases.__len__()
|
||
if bn == 0:
|
||
return None
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
bname: str = _get_base_name(base_node, pool)
|
||
if bname is not None and _is_marker_base(bname) == 0:
|
||
return bname
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# _trigger_base_specialization — 触发 base 中 Subscript 的泛型特化
|
||
#
|
||
# 对于 class Value(GSListNode[Value]),GSListNode[Value] 是 Subscript 节点。
|
||
# 在 translate_class_def 处理 Value 之前,需要先特化 GSListNode[Value],
|
||
# 否则 find_struct_by_module("GSListNode[Value]") 返回 None,父类字段不被继承。
|
||
#
|
||
# 遍历 cd.bases,如果 base 是 Subscript,提取 class_name 和 type_args,
|
||
# 调用 _specialize_generic_class 触发特化。
|
||
# ============================================================
|
||
def _trigger_base_specialization(trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr):
|
||
"""触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])"""
|
||
if trans is None or cd is None or cd.bases is None:
|
||
return
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = bases.__len__()
|
||
if bn == 0:
|
||
return
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
bk: int = base_node.kind()
|
||
if bk != ast.ASTKind.Subscript:
|
||
continue
|
||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node)
|
||
if sub is None or sub.value is None or sub.slice is None:
|
||
continue
|
||
# 提取泛型类名(如 "GSListNode")
|
||
gen_class_name: str = _get_base_name(sub.value, pool)
|
||
if gen_class_name is None:
|
||
continue
|
||
# 跳过标记基类
|
||
if _is_marker_base(gen_class_name) == 1:
|
||
continue
|
||
# 提取类型实参名(如 "Value")
|
||
slice_k: int = sub.slice.kind()
|
||
arg_nm: str = None
|
||
if slice_k == ast.ASTKind.Name:
|
||
sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice)
|
||
arg_nm = sl_nm.id
|
||
if arg_nm is None:
|
||
continue
|
||
# 构建 type_args 列表
|
||
type_args: list[str] | t.CPtr = list[str](pool, 1)
|
||
if type_args is None:
|
||
continue
|
||
type_args.append(arg_nm)
|
||
# 触发特化(_specialize_generic_class 有缓存,重复调用安全)
|
||
_specialize_generic_class(trans, gen_class_name, type_args)
|
||
|
||
|
||
# ============================================================
|
||
# _has_any_func_cvtable — 检查类中是否有任何函数标记了 @t.CVTable
|
||
#
|
||
# 用于类级别未启用虚表时,检查函数级 @t.CVTable 是否触发虚表。
|
||
# 跳过 __init__ 和 __before_init__(构造函数不进入虚表)。
|
||
# ============================================================
|
||
def _has_any_func_cvtable(cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无"""
|
||
if cd is None or cd.children is None:
|
||
return 0
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
cn: t.CSizeT = children.__len__()
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd is None or fd.name is None:
|
||
continue
|
||
# 跳过构造函数
|
||
if string.strcmp(fd.name, "__init__") == 0:
|
||
continue
|
||
if string.strcmp(fd.name, "__before_init__") == 0:
|
||
continue
|
||
if string.strcmp(fd.name, "__new__") == 0:
|
||
continue
|
||
if fd.decorator_list is not None:
|
||
if _has_decorator(fd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _should_method_be_virtual — 判断方法是否应该进入虚表
|
||
#
|
||
# 规则(优先级从高到低):
|
||
# 1. 函数有 @t.NoVTable → 排除(返回 0)
|
||
# 2. 函数有 @t.CVTable → 包含(返回 1)
|
||
# 3. 类有 @t.CVTable → 包含(返回 1)
|
||
# 4. 有继承关系(父类非 NoVTable)→ 包含(返回 1)
|
||
# 5. 默认 → 排除(返回 0)
|
||
# ============================================================
|
||
def _should_method_be_virtual(cd: ast.ClassDef | t.CPtr,
|
||
fd: ast.FunctionDef | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = None) -> int:
|
||
"""判断方法是否应该进入虚表,返回 1=包含 / 0=排除"""
|
||
if fd is None:
|
||
return 0
|
||
# 1. 检查函数级 @t.NoVTable(最高优先级,排除)
|
||
if fd.decorator_list is not None:
|
||
if _has_decorator(fd.decorator_list, "NoVTable") == 1:
|
||
return 0
|
||
# 2. 检查函数级 @t.CVTable(明确包含)
|
||
if _has_decorator(fd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
|
||
# 3. 检查类级别 @t.CVTable
|
||
if cd is not None and cd.decorator_list is not None:
|
||
if _has_decorator(cd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
|
||
# 4. 检查继承关系
|
||
parent_name: str = _get_parent_class(cd, trans)
|
||
if parent_name is not None:
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
is_nvt: int = 0
|
||
if trans is not None:
|
||
p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if p_entry is not None:
|
||
is_nvt = p_entry.IsNoVTable
|
||
else:
|
||
is_nvt = HandlesStruct.is_novtable_by_name(parent_name)
|
||
if is_nvt != 1:
|
||
return 1 # 有继承且父类非 NoVTable
|
||
|
||
# 5. 默认排除
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _detect_vtable_status — 检测类是否应该启用虚表
|
||
#
|
||
# 规则:
|
||
# 1. @t.CVTable → 有虚表
|
||
# 2. 有真实父类且非 NoVTable → 有虚表(自动启用)
|
||
# 3. @t.NoVTable → 检查函数级 @t.CVTable,有则启用
|
||
# 4. 默认 → 检查函数级 @t.CVTable,有则启用
|
||
#
|
||
# 返回: 1=有虚表 / 0=无虚表
|
||
# ============================================================
|
||
def _detect_vtable_status(cd: ast.ClassDef | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = None) -> int:
|
||
"""检测类是否应该启用虚表"""
|
||
if cd is None:
|
||
return 0
|
||
|
||
# 检查类装饰器
|
||
if cd.decorator_list is not None:
|
||
# @t.CVTable 优先级最高,直接启用
|
||
if _has_decorator(cd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
# @t.NoVTable:类级别禁用,但检查函数级 @t.CVTable
|
||
if _has_decorator(cd.decorator_list, "NoVTable") == 1:
|
||
return _has_any_func_cvtable(cd)
|
||
|
||
# 检查是否有真实父类(继承自动启用 CVTable)
|
||
parent_name: str = _get_parent_class(cd, trans)
|
||
if parent_name is not None:
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
is_nvt: int = 0
|
||
if trans is not None:
|
||
p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if p_entry is not None:
|
||
is_nvt = p_entry.IsNoVTable
|
||
else:
|
||
is_nvt = HandlesStruct.is_novtable_by_name(parent_name)
|
||
if is_nvt == 1:
|
||
# 父类是 NoVTable,检查函数级 @t.CVTable
|
||
return _has_any_func_cvtable(cd)
|
||
return 1 # 有父类且非 NoVTable,自动启用虚表
|
||
|
||
# 默认(无装饰器无继承),检查函数级 @t.CVTable
|
||
return _has_any_func_cvtable(cd)
|
||
|
||
|
||
# ============================================================
|
||
# _resolve_enum_member_type — 解析枚举成员的类型
|
||
#
|
||
# - t.State → 默认 i32
|
||
# - int / t.CInt8T / t.CInt16T / t.CInt32T / t.CInt64T 等 → 对应整数类型
|
||
# - 联合注解(t.State | t.CInt8T)递归查找实际类型
|
||
# ============================================================
|
||
def _resolve_enum_member_type(pool: memhub.MemBuddy | t.CPtr,
|
||
ann_node: ast.AST | t.CPtr,
|
||
imported_modules: str,
|
||
from_imports: str) -> llvmlite.LLVMType | t.CPtr:
|
||
"""解析枚举成员的类型注解为 LLVM 整数类型"""
|
||
if ann_node is None:
|
||
return llvmlite.Int32(pool)
|
||
|
||
k: int = ann_node.kind()
|
||
|
||
# Attribute 节点: t.State / int / t.CInt8T 等
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(ann_node)
|
||
if at.attr is None:
|
||
return llvmlite.Int32(pool)
|
||
# t.State → 默认 i32
|
||
if string.strcmp(at.attr, "State") == 0:
|
||
return llvmlite.Int32(pool)
|
||
# 其他 t.CXxx 类型
|
||
ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr)
|
||
if ty is not None:
|
||
return ty
|
||
return llvmlite.Int32(pool)
|
||
|
||
# Name 节点: from-import 形式(State / CInt)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ann_node)
|
||
if nm.id is None:
|
||
return llvmlite.Int32(pool)
|
||
if string.strcmp(nm.id, "State") == 0:
|
||
return llvmlite.Int32(pool)
|
||
ty2: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, nm.id)
|
||
if ty2 is not None:
|
||
return ty2
|
||
return llvmlite.Int32(pool)
|
||
|
||
# BinOp 节点: t.State | t.CInt8T(递归查找实际类型)
|
||
if k == ast.ASTKind.BinOp:
|
||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(ann_node)
|
||
if bop.op == ast.OpKind.BitOr:
|
||
left_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type(
|
||
pool, bop.left, imported_modules, from_imports)
|
||
# 跳过 t.State(i32 默认),优先返回具体类型
|
||
left_bits: int = HandlesType.get_llvm_type_bits(left_ty)
|
||
if left_bits != 0 and not _is_state_annotation(bop.left):
|
||
return left_ty
|
||
right_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type(
|
||
pool, bop.right, imported_modules, from_imports)
|
||
if right_ty is not None and not _is_state_annotation(bop.right):
|
||
return right_ty
|
||
# 两边都是 State 或无法确定,返回较宽的
|
||
right_bits: int = HandlesType.get_llvm_type_bits(right_ty)
|
||
if left_bits >= right_bits:
|
||
return left_ty
|
||
return right_ty
|
||
return llvmlite.Int32(pool)
|
||
|
||
return llvmlite.Int32(pool)
|
||
|
||
|
||
# ============================================================
|
||
# _is_state_annotation — 检查注解节点是否为 t.State
|
||
# ============================================================
|
||
def _is_state_annotation(node: ast.AST | t.CPtr) -> int:
|
||
"""检查注解节点是否为 t.State,返回 1=是 / 0=否"""
|
||
if node is None:
|
||
return 0
|
||
k: int = node.kind()
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||
if at.attr is not None and string.strcmp(at.attr, "State") == 0:
|
||
return 1
|
||
return 0
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||
if nm.id is not None and string.strcmp(nm.id, "State") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _extract_int_value — 从 AST 节点提取整数值
|
||
#
|
||
# 支持 Constant(int) 和 UnaryOp(USub, Constant(int))
|
||
# ============================================================
|
||
def _extract_int_value(node: ast.AST | t.CPtr) -> t.CInt64T:
|
||
"""从 AST 节点提取整数值,失败返回 0"""
|
||
if node is None:
|
||
return 0
|
||
k: int = node.kind()
|
||
if k == ast.ASTKind.Constant:
|
||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||
if cn.const_kind == ast.CONST_INT:
|
||
return cn.int_val
|
||
return 0
|
||
if k == ast.ASTKind.UnaryOp:
|
||
uo: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
|
||
if uo.op == ast.OpKind.USub:
|
||
inner: t.CInt64T = _extract_int_value(uo.operand)
|
||
return -inner
|
||
return 0
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _translate_enum_def — 翻译枚举类定义
|
||
#
|
||
# 遍历 class body 中的 AnnAssign,收集成员名、类型、值
|
||
# 自动赋值:无值时从上一值+1递增(首值默认 0)
|
||
# 基准类型:所有成员类型中 Bits 最大的(t.State 视为 i32)
|
||
# ============================================================
|
||
def _translate_enum_def(trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""翻译枚举类定义,返回 0"""
|
||
if cd is None or cd.name is None or trans is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
class_name: str = cd.name
|
||
|
||
# 已注册则跳过
|
||
if HandlesEnum.is_enum_class(class_name) == 1:
|
||
return 0
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "%s has no body", class_name)
|
||
VLogger.warning(fb, "ENUM")
|
||
return 0
|
||
|
||
cn: t.CSizeT = children.__len__()
|
||
|
||
# 临时数组存储成员信息
|
||
member_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL)
|
||
member_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL)
|
||
member_values_buf: t.CInt64T | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL)
|
||
if member_names_buf is None or member_types_buf is None or member_values_buf is None:
|
||
return 0
|
||
string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL)
|
||
string.memset(member_types_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL)
|
||
string.memset(member_values_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL)
|
||
|
||
member_count: int = 0
|
||
next_val: t.CInt64T = 0
|
||
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
sk: int = stmt.kind()
|
||
|
||
if sk == ast.ASTKind.AnnAssign:
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
|
||
if aa is None or aa.target is None:
|
||
continue
|
||
|
||
# 获取成员名
|
||
if aa.target.kind() != ast.ASTKind.Name:
|
||
continue
|
||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||
if tgt.id is None:
|
||
continue
|
||
|
||
# 解析成员类型
|
||
member_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type(
|
||
pool, aa.annotation, trans._imported_modules, trans._from_imports)
|
||
|
||
# 解析成员值
|
||
has_value: int = 0
|
||
cur_val: t.CInt64T = 0
|
||
if aa.value is not None:
|
||
cur_val = _extract_int_value(aa.value)
|
||
has_value = 1
|
||
else:
|
||
cur_val = next_val
|
||
|
||
# 下一个自动值
|
||
next_val = cur_val + 1
|
||
|
||
# 存储
|
||
if member_count < ENUM_MEMBER_MAX_LOCAL:
|
||
member_names_buf[member_count] = t.CSizeT(tgt.id)
|
||
member_types_buf[member_count] = t.CSizeT(member_ty)
|
||
member_values_buf[member_count] = cur_val
|
||
member_count += 1
|
||
|
||
elif sk == ast.ASTKind.Assign:
|
||
# 处理 Assign 形式的枚举成员: DEBUG = 0, INFO = 1 等
|
||
# CEnum 子类中无类型注释的赋值也视为枚举成员
|
||
ag: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(stmt)
|
||
if ag is None or ag.targets is None:
|
||
continue
|
||
tgts: list[ast.AST | t.CPtr] | t.CPtr = ag.targets
|
||
tn: t.CSizeT = tgts.__len__()
|
||
if tn == 0:
|
||
continue
|
||
# 取第一个 target 作为成员名
|
||
t0: ast.AST | t.CPtr = tgts.get(0)
|
||
if t0 is None or t0.kind() != ast.ASTKind.Name:
|
||
continue
|
||
tgt_a: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0)
|
||
if tgt_a.id is None:
|
||
continue
|
||
|
||
# Assign 无类型注释,默认使用 i32
|
||
member_ty_a: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
|
||
# 解析成员值
|
||
cur_val_a: t.CInt64T = 0
|
||
if ag.value is not None:
|
||
cur_val_a = _extract_int_value(ag.value)
|
||
else:
|
||
cur_val_a = next_val
|
||
|
||
# 下一个自动值
|
||
next_val = cur_val_a + 1
|
||
|
||
# 存储
|
||
if member_count < ENUM_MEMBER_MAX_LOCAL:
|
||
member_names_buf[member_count] = t.CSizeT(tgt_a.id)
|
||
member_types_buf[member_count] = t.CSizeT(member_ty_a)
|
||
member_values_buf[member_count] = cur_val_a
|
||
member_count += 1
|
||
|
||
if member_count == 0:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "%s has no members", class_name)
|
||
VLogger.warning(fb, "ENUM")
|
||
return 0
|
||
|
||
# 确定基准类型:所有成员类型中 Bits 最大的
|
||
base_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
max_bits: int = 0
|
||
for mi in range(member_count):
|
||
ty_addr: t.CSizeT = member_types_buf[mi]
|
||
if ty_addr == 0:
|
||
continue
|
||
mty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
|
||
t.CVoid(ty_addr, t.CPtr))
|
||
bits: int = HandlesType.get_llvm_type_bits(mty)
|
||
if bits > max_bits:
|
||
max_bits = bits
|
||
base_ty = mty
|
||
|
||
# 注册枚举
|
||
entry: HandlesEnum.EnumEntry | t.CPtr = HandlesEnum.register_enum(
|
||
pool, class_name, base_ty)
|
||
if entry is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "failed to register %s", class_name)
|
||
VLogger.error(fb, "ENUM")
|
||
return 0
|
||
|
||
# 添加成员
|
||
for mi in range(member_count):
|
||
fname_addr: t.CSizeT = member_names_buf[mi]
|
||
if fname_addr == 0:
|
||
continue
|
||
mname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
|
||
fty_addr2: t.CSizeT = member_types_buf[mi]
|
||
if fty_addr2 == 0:
|
||
continue
|
||
mty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
|
||
t.CVoid(fty_addr2, t.CPtr))
|
||
mval: t.CInt64T = member_values_buf[mi]
|
||
if mname is not None and mty2 is not None:
|
||
HandlesEnum.add_enum_member(pool, entry, mname, mval, mty2)
|
||
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "registered %s with %d members, base_bits=%d",
|
||
class_name, member_count, max_bits)
|
||
VLogger.info(fb, "ENUM")
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _get_type_size — 计算 LLVM 类型的字节大小
|
||
#
|
||
# 用于联合体确定最大字段大小
|
||
# ============================================================
|
||
def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||
"""计算 LLVM 类型的字节大小"""
|
||
if ty is None:
|
||
return 0
|
||
match ty:
|
||
case llvmlite.LLVMType.Int(bits):
|
||
return (bits + 7) // 8
|
||
case llvmlite.LLVMType.Float(bits):
|
||
return bits // 8
|
||
case llvmlite.LLVMType.Ptr(pointee):
|
||
return 8
|
||
case llvmlite.LLVMType.Array(elem_ty, count):
|
||
return _get_type_size(elem_ty) * count
|
||
case llvmlite.LLVMType.Struct(fields, fcount, name):
|
||
total: int = 0
|
||
cur: llvmlite.ParamNode | t.CPtr = fields
|
||
i: int = 0
|
||
while cur is not None and i < fcount:
|
||
if cur.Ty is not None:
|
||
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
|
||
total += _get_type_size(fty)
|
||
cur = cur.Next
|
||
i += 1
|
||
return total
|
||
case _:
|
||
return 8
|
||
|
||
|
||
# ============================================================
|
||
# _translate_union_def — 翻译联合体定义
|
||
#
|
||
# 联合体语法:
|
||
# class MyUnion(t.CUnion):
|
||
# a: t.CInt
|
||
# b: t.CFloat
|
||
# c: t.CInt64T
|
||
#
|
||
# 实现方式:
|
||
# - 收集所有字段类型
|
||
# - 计算最大字段字节大小 max_size
|
||
# - LLVM 类型 = Struct([Array(Int8, max_size)]) # { [N x i8] }
|
||
# - 注册到 HandlesStruct 并标记 IsUnion=1
|
||
# - 字段访问通过 bitcast 实现(HandlesExpr 中处理)
|
||
# ============================================================
|
||
def _translate_union_def(trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""翻译联合体定义,返回 0"""
|
||
if cd is None or cd.name is None or trans is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
class_name: str = cd.name
|
||
|
||
# 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前)
|
||
HandlesStruct.add_visible_struct(pool, class_name)
|
||
|
||
# 检查是否已注册(用 SHA1 区分跨模块同名类)
|
||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
if existing is not None:
|
||
# Phase B: 将已存在的命名结构体注册到当前模块
|
||
if existing.Ty is not None:
|
||
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
|
||
# SHA1 已在 register_struct 时设置,无需再补
|
||
return 0
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "%s has no body", class_name)
|
||
VLogger.warning(fb, "UNION")
|
||
return 0
|
||
|
||
cn: t.CSizeT = children.__len__()
|
||
|
||
# 临时数组存储字段信息
|
||
field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48)
|
||
field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48)
|
||
if field_names_buf is None or field_types_buf is None:
|
||
return 0
|
||
string.memset(field_names_buf, 0, 8 * 48)
|
||
string.memset(field_types_buf, 0, 8 * 48)
|
||
|
||
field_count: int = 0
|
||
max_size: int = 0
|
||
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
sk: int = stmt.kind()
|
||
|
||
if sk == ast.ASTKind.AnnAssign:
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
|
||
if aa is None or aa.target is None:
|
||
continue
|
||
|
||
# 获取字段名
|
||
if aa.target.kind() != ast.ASTKind.Name:
|
||
continue
|
||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||
if tgt.id is None:
|
||
continue
|
||
|
||
# 解析字段类型
|
||
field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||
if field_ty is None:
|
||
field_ty = llvmlite.Int32(pool)
|
||
|
||
# 计算字段大小,更新 max_size
|
||
fsize: int = _get_type_size(field_ty)
|
||
if fsize > max_size:
|
||
max_size = fsize
|
||
|
||
# 存储到数组
|
||
if field_count < 48:
|
||
field_names_buf[field_count] = t.CSizeT(tgt.id)
|
||
field_types_buf[field_count] = t.CSizeT(field_ty)
|
||
field_count += 1
|
||
|
||
if field_count == 0:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "%s has no fields", class_name)
|
||
VLogger.warning(fb, "UNION")
|
||
return 0
|
||
|
||
if max_size < 1:
|
||
max_size = 1
|
||
|
||
# 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)])
|
||
# 即 { [max_size x i8] }
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
array_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, max_size)
|
||
|
||
# 构建 ParamNode 链表(单字段:字节数组)
|
||
pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if pnode is None:
|
||
return 0
|
||
string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
|
||
pnode.Ty = array_ty
|
||
|
||
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
|
||
union_type_name: str = class_name
|
||
if trans.ModuleSha1 is not None:
|
||
union_name_buf: t.CChar | t.CPtr = pool.alloc(64)
|
||
if union_name_buf is not None:
|
||
viperlib.snprintf(union_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
|
||
union_type_name = union_name_buf
|
||
|
||
union_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, pnode, 1, union_type_name)
|
||
if union_ty is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name)
|
||
VLogger.error(fb, "UNION")
|
||
return 0
|
||
|
||
# 注册命名结构体到模块
|
||
llvmlite.module_add_named_type(trans.Module, pool, union_ty)
|
||
|
||
# 注册到 HandlesStruct(传递 SHA1 在注册时直接设置,避免跨模块同名找错 entry)
|
||
entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct(
|
||
pool, class_name, union_ty, trans.ModuleSha1)
|
||
if entry is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "failed to register %s", class_name)
|
||
VLogger.error(fb, "UNION")
|
||
return 0
|
||
|
||
# 标记为当前文件可见(命名空间隔离)
|
||
HandlesStruct.add_visible_struct(pool, class_name)
|
||
|
||
# 标记为联合体(直接用 entry,规避跨模块同名 find_struct 找错)
|
||
entry.IsUnion = 1
|
||
|
||
# 添加字段信息(所有字段 Index=0,因为共享偏移 0)
|
||
for fi in range(field_count):
|
||
fname_addr: t.CSizeT = field_names_buf[fi]
|
||
if fname_addr == 0:
|
||
continue
|
||
fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
|
||
fty_addr2: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr2 == 0:
|
||
continue
|
||
fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
|
||
t.CVoid(fty_addr2, t.CPtr))
|
||
if fname is not None and fty2 is not None:
|
||
HandlesStruct.add_field(pool, entry, fname, fty2, None, None)
|
||
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "registered %s with %d fields, max_size=%d",
|
||
class_name, field_count, max_size)
|
||
VLogger.info(fb, "UNION")
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _get_annotation_field_size — 计算注解类型的字节大小
|
||
#
|
||
# 用于 REnum 布局计算,不要求类型已注册(避免自引用死锁)。
|
||
# 联合类型 (A | B) 按指针 8 字节处理。
|
||
# 未知类型默认 8 字节(指针)。
|
||
# ============================================================
|
||
def _get_annotation_field_size(annotation: ast.AST | t.CPtr) -> int:
|
||
"""计算注解类型的字节大小,用于 REnum 布局计算"""
|
||
if annotation is None:
|
||
return 8
|
||
k: int = annotation.kind()
|
||
# 联合类型 A | B → 指针大小 8
|
||
if k == ast.ASTKind.BinOp:
|
||
return 8
|
||
# Name(id) 或 Attribute(attr) → 解析类型名
|
||
type_name: str = None
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annotation)
|
||
if nm is not None:
|
||
type_name = nm.id
|
||
elif k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation)
|
||
if at is not None:
|
||
type_name = at.attr
|
||
if type_name is None:
|
||
return 8
|
||
# 内置类型
|
||
if string.strcmp(type_name, "int") == 0:
|
||
return 4
|
||
if string.strcmp(type_name, "CInt") == 0:
|
||
return 4
|
||
if string.strcmp(type_name, "CInt8T") == 0:
|
||
return 1
|
||
if string.strcmp(type_name, "CInt16T") == 0:
|
||
return 2
|
||
if string.strcmp(type_name, "CInt32T") == 0:
|
||
return 4
|
||
if string.strcmp(type_name, "CInt64T") == 0:
|
||
return 8
|
||
if string.strcmp(type_name, "CChar") == 0:
|
||
return 1
|
||
if string.strcmp(type_name, "CDouble") == 0:
|
||
return 8
|
||
if string.strcmp(type_name, "CFloat") == 0:
|
||
return 4
|
||
if string.strcmp(type_name, "CPtr") == 0:
|
||
return 8
|
||
if string.strcmp(type_name, "CSizeT") == 0:
|
||
return 8
|
||
if string.strcmp(type_name, "str") == 0:
|
||
return 8
|
||
if string.strcmp(type_name, "bytes") == 0:
|
||
return 8
|
||
if string.strcmp(type_name, "bool") == 0:
|
||
return 4
|
||
# 已注册的结构体类型
|
||
struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(type_name)
|
||
if struct_ty is not None:
|
||
sz: int = _get_type_size(struct_ty)
|
||
if sz > 0:
|
||
return sz
|
||
# 未注册类型 → 默认指针大小 8(可能是自引用或前向引用)
|
||
return 8
|
||
|
||
|
||
# ============================================================
|
||
# _translate_renum_def — 翻译 REnum 类定义
|
||
#
|
||
# REnum 语法:
|
||
# class LLVMType(t.REnum):
|
||
# class Int:
|
||
# Bits: t.CInt
|
||
# class Ptr:
|
||
# Pointee: LLVMType | t.CPtr
|
||
# ...
|
||
#
|
||
# 内存布局: {i32 __tag, <field1>, <field2>, ...}
|
||
# 每个字段位置取所有变体在该位置的最大字段大小:
|
||
# - max_size <= 4 → i32
|
||
# - max_size > 4 → i64(可容纳指针)
|
||
# 至少包含 {i32, i32}(tag + 最小 payload)
|
||
#
|
||
# 对应 TPC 中 HandlesClassDef._RegisterREnumMembers 的逻辑
|
||
# ============================================================
|
||
def _translate_renum_def(trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""翻译 REnum 类定义,返回 0"""
|
||
if cd is None or cd.name is None or trans is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
class_name: str = cd.name
|
||
|
||
# 命名空间隔离:标记为当前文件可见
|
||
HandlesStruct.add_visible_struct(pool, class_name)
|
||
|
||
# 检查是否已注册(用 SHA1 区分跨模块同名类)
|
||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
if existing is not None:
|
||
if existing.Ty is not None:
|
||
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
|
||
return 0
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "%s has no body", class_name)
|
||
VLogger.warning(fb, "RENUM")
|
||
return 0
|
||
|
||
cn: t.CSizeT = children.__len__()
|
||
|
||
# 变体最多 32 个,每个变体最多 16 个字段
|
||
# variant_field_sizes[i][j] = 变体 i 的第 j 个字段大小
|
||
variant_field_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * 48 * 16)
|
||
if variant_field_sizes is None:
|
||
return 0
|
||
string.memset(variant_field_sizes, 0, 8 * 48 * 16)
|
||
|
||
variant_count: int = 0
|
||
max_field_count: int = 0 # 所有变体中最大字段数
|
||
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
sk: int = stmt.kind()
|
||
|
||
if sk == ast.ASTKind.ClassDef:
|
||
# 嵌套变体类
|
||
variant_cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt)
|
||
if variant_cd is None or variant_cd.children is None:
|
||
variant_count += 1
|
||
continue
|
||
variant_children: list[ast.AST | t.CPtr] | t.CPtr = variant_cd.children
|
||
vcn: t.CSizeT = variant_children.__len__()
|
||
field_idx: int = 0
|
||
for vi in range(vcn):
|
||
vstmt: ast.AST | t.CPtr = variant_children.get(vi)
|
||
if vstmt is None:
|
||
continue
|
||
vk: int = vstmt.kind()
|
||
if vk != ast.ASTKind.AnnAssign:
|
||
continue
|
||
vaa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(vstmt)
|
||
if vaa is None or vaa.target is None or vaa.annotation is None:
|
||
continue
|
||
if vaa.target.kind() != ast.ASTKind.Name:
|
||
continue
|
||
# 提取字段名
|
||
vnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(vaa.target)
|
||
# 计算字段大小
|
||
fsize: int = _get_annotation_field_size(vaa.annotation)
|
||
if variant_count < 32 and field_idx < 16:
|
||
# variant_field_sizes[variant_count][field_idx] = fsize
|
||
offset: t.CSizeT = variant_count * 16 + field_idx
|
||
variant_field_sizes[offset] = t.CSizeT(fsize)
|
||
# 直接注册变体字段名别名(避免 CSizeT→str 转换问题)
|
||
if vnm is not None and vnm.id is not None:
|
||
_register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1)
|
||
field_idx += 1
|
||
if field_idx > max_field_count:
|
||
max_field_count = field_idx
|
||
variant_count += 1
|
||
|
||
if variant_count == 0:
|
||
fb2: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb2 is not None:
|
||
viperlib.snprintf(fb2, 1024, "%s has no variants", class_name)
|
||
VLogger.warning(fb2, "RENUM")
|
||
return 0
|
||
|
||
# 计算每个位置的最大字段大小
|
||
# 位置 0 = __tag (i32, 4 字节)
|
||
# 位置 1+ = 变体字段
|
||
total_positions: int = max_field_count + 1 # +1 for tag
|
||
if total_positions < 2:
|
||
total_positions = 2 # 至少 {i32, i32}
|
||
|
||
position_max_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * total_positions)
|
||
if position_max_sizes is None:
|
||
return 0
|
||
string.memset(position_max_sizes, 0, 8 * total_positions)
|
||
|
||
# 位置 0 = tag = 4 字节
|
||
position_max_sizes[0] = t.CSizeT(4)
|
||
|
||
# 位置 1+ = 每个位置取所有变体的最大字段大小
|
||
for pos in range(1, total_positions):
|
||
pos_max: int = 0
|
||
for vi in range(variant_count):
|
||
field_pos: int = pos - 1 # 变体字段从位置 0 开始
|
||
offset2: t.CSizeT = vi * 16 + field_pos
|
||
fsize_val: t.CSizeT = variant_field_sizes[offset2]
|
||
if fsize_val > pos_max:
|
||
pos_max = fsize_val
|
||
position_max_sizes[pos] = t.CSizeT(pos_max)
|
||
|
||
# 构建 ParamNode 链表
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||
|
||
first_node: llvmlite.ParamNode | t.CPtr = None
|
||
tail_node: llvmlite.ParamNode | t.CPtr = None
|
||
|
||
for pos in range(total_positions):
|
||
psize: int = position_max_sizes[pos]
|
||
field_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if psize > 4:
|
||
field_ty = i64_ty
|
||
pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, field_ty)
|
||
if pnode is None:
|
||
continue
|
||
tail_node = llvmlite.param_list_append(first_node, tail_node, pnode)
|
||
if first_node is None:
|
||
first_node = tail_node
|
||
|
||
if first_node is None:
|
||
fb3: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb3 is not None:
|
||
viperlib.snprintf(fb3, 1024, "failed to build field list for %s", class_name)
|
||
VLogger.error(fb3, "RENUM")
|
||
return 0
|
||
|
||
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
|
||
renum_type_name: str = class_name
|
||
if trans.ModuleSha1 is not None:
|
||
renum_name_buf: t.CChar | t.CPtr = pool.alloc(64)
|
||
if renum_name_buf is not None:
|
||
viperlib.snprintf(renum_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
|
||
renum_type_name = renum_name_buf
|
||
|
||
renum_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(
|
||
pool, first_node, total_positions, renum_type_name)
|
||
if renum_ty is None:
|
||
fb4: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb4 is not None:
|
||
viperlib.snprintf(fb4, 1024, "failed to create type for %s", class_name)
|
||
VLogger.error(fb4, "RENUM")
|
||
return 0
|
||
|
||
# 注册命名结构体到模块
|
||
llvmlite.module_add_named_type(trans.Module, pool, renum_ty)
|
||
|
||
# 注册到 HandlesStruct
|
||
entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct(
|
||
pool, class_name, renum_ty, trans.ModuleSha1)
|
||
if entry is None:
|
||
fb5: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb5 is not None:
|
||
viperlib.snprintf(fb5, 1024, "failed to register %s", class_name)
|
||
VLogger.error(fb5, "RENUM")
|
||
return 0
|
||
|
||
# 修复 class_name 指针不匹配:
|
||
# 别名注册时用 class_name(= cd.name,AST 原始指针),
|
||
# 但查找时用 entry.Name(register_struct 通过 pool.alloc+strcpy 复制的副本指针)。
|
||
# 两者是不同指针,CSizeT 指针值比较会失败。
|
||
# 调用辅助函数将已注册别名的 class_name 统一更新为 entry.Name。
|
||
if entry.Name is not None:
|
||
_update_renum_alias_class_ptr(t.CSizeT(class_name), t.CSizeT(entry.Name))
|
||
|
||
# 添加 __tag 字段(位置 0,i32)
|
||
HandlesStruct.add_field(pool, entry, "__tag", i32_ty, None, None)
|
||
|
||
# 添加 payload 字段(位置 1+,i32 或 i64)
|
||
for pos in range(1, total_positions):
|
||
psize2: int = position_max_sizes[pos]
|
||
payload_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if psize2 > 4:
|
||
payload_ty = i64_ty
|
||
field_name_buf: t.CChar | t.CPtr = pool.alloc(16)
|
||
if field_name_buf is not None:
|
||
viperlib.snprintf(field_name_buf, 16, "_p%d", pos)
|
||
HandlesStruct.add_field(pool, entry, field_name_buf, payload_ty, None, None)
|
||
|
||
# 注册变体名到全局变体表(供 translate_call 检测 REnum 变体构造)
|
||
_register_renum_variants(pool, class_name, cd, variant_count)
|
||
|
||
# 注册变体字段名别名已在变体遍历时直接完成(避免 CSizeT→str 转换问题)
|
||
|
||
fb6: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb6 is not None:
|
||
viperlib.snprintf(fb6, 1024, "registered %s with %d variants, %d positions",
|
||
class_name, variant_count, total_positions)
|
||
VLogger.info(fb6, "RENUM")
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# REnum 变体表(全局静态分配)
|
||
#
|
||
# 存储 ClassName → [VariantName, TagValue] 映射,
|
||
# 供 translate_call 检测 ClassName.VariantName(args) 形式的变体构造调用。
|
||
#
|
||
# 布局(所有数组使用 t.CSizeT | t.CPtr 确保 8 字节步长):
|
||
# _renum_class_names[i] = 第 i 个 REnum 类名(str 指针,以 CSizeT 存储)
|
||
# _renum_class_variant_counts[i] = 第 i 个 REnum 类的变体数量
|
||
# _renum_variant_names[i][j] = 第 i 个类的第 j 个变体名(str 指针,以 CSizeT 存储)
|
||
# _renum_variant_tags[i][j] = 第 i 个类的第 j 个变体的 tag 值
|
||
# ============================================================
|
||
_renum_class_names: t.CSizeT | t.CPtr = None
|
||
_renum_class_variant_counts: t.CSizeT | t.CPtr = None
|
||
_renum_variant_names: t.CSizeT | t.CPtr = None
|
||
_renum_variant_tags: t.CSizeT | t.CPtr = None
|
||
_renum_class_count: int = 0
|
||
|
||
|
||
# ============================================================
|
||
# REnum 字段别名表(全局静态分配)
|
||
#
|
||
# 存储 (class_name, field_name) → payload_index 映射,
|
||
# 供 translate_attribute 查找 REnum 变体字段。
|
||
#
|
||
# REnum 结构体布局为 {i32 __tag, _p1, _p2, ...},
|
||
# 但源码用变体字段名访问(如 ty.Pointee)。
|
||
# 此表将变体字段名映射到 payload 索引(_p1=1, _p2=2, ...)。
|
||
#
|
||
# 布局:
|
||
# _renum_alias_class[i] = 类名(str 指针,以 CSizeT 存储)
|
||
# _renum_alias_field[i] = 字段名(str 指针,以 CSizeT 存储)
|
||
# _renum_alias_index[i] = payload 索引(CSizeT)
|
||
# ============================================================
|
||
RENUM_ALIAS_MAX: t.CDefine = 512
|
||
_renum_alias_class: t.CSizeT | t.CPtr = None
|
||
_renum_alias_field: t.CSizeT | t.CPtr = None
|
||
_renum_alias_index: t.CSizeT | t.CPtr = None
|
||
_renum_alias_count: int = 0
|
||
|
||
|
||
# ============================================================
|
||
# _register_renum_variants — 注册 REnum 类的变体名和 tag 值
|
||
#
|
||
# 遍历 ClassDef 的 children,提取嵌套变体类的名称,
|
||
# 按 children 顺序分配 tag 值(0, 1, 2, ...)
|
||
#
|
||
# 参数:
|
||
# pool: 内存分配器
|
||
# class_name: REnum 类名(如 "LLVMType")
|
||
# cd: REnum 类的 ClassDef AST 节点
|
||
# variant_count: 变体数量(由 _translate_renum_def 预计算)
|
||
# ============================================================
|
||
def _register_renum_variants(pool: memhub.MemBuddy | t.CPtr,
|
||
class_name: str,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
variant_count: int):
|
||
"""注册 REnum 类的变体名和 tag 值到全局变体表"""
|
||
global _renum_class_names, _renum_class_variant_counts
|
||
global _renum_variant_names, _renum_variant_tags, _renum_class_count
|
||
|
||
if pool is None or class_name is None or cd is None:
|
||
return
|
||
if variant_count == 0:
|
||
return
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return
|
||
|
||
# 懒初始化表(首次注册时分配)
|
||
if _renum_class_names is None:
|
||
_renum_class_names = pool.alloc(8 * RENUM_CLASS_MAX)
|
||
_renum_class_variant_counts = pool.alloc(8 * RENUM_CLASS_MAX)
|
||
_renum_variant_names = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
|
||
_renum_variant_tags = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
|
||
if (_renum_class_names is None or _renum_class_variant_counts is None
|
||
or _renum_variant_names is None or _renum_variant_tags is None):
|
||
_renum_class_names = None
|
||
return
|
||
string.memset(_renum_class_names, 0, 8 * RENUM_CLASS_MAX)
|
||
string.memset(_renum_class_variant_counts, 0, 8 * RENUM_CLASS_MAX)
|
||
string.memset(_renum_variant_names, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
|
||
string.memset(_renum_variant_tags, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
|
||
_renum_class_count = 0
|
||
|
||
# 检查是否已注册(避免重复注册)
|
||
for i in range(_renum_class_count):
|
||
existing: str = _renum_class_names[i]
|
||
if existing is not None and string.strcmp(existing, class_name) == 0:
|
||
return
|
||
|
||
# 表已满
|
||
if _renum_class_count >= RENUM_CLASS_MAX:
|
||
return
|
||
|
||
# 注册类名
|
||
idx: int = _renum_class_count
|
||
_renum_class_names[idx] = t.CSizeT(class_name)
|
||
_renum_class_variant_counts[idx] = variant_count
|
||
|
||
# 遍历 children,提取嵌套变体类名并注册
|
||
cn: t.CSizeT = children.__len__()
|
||
tag: int = 0
|
||
for ci in range(cn):
|
||
if tag >= variant_count:
|
||
break
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() != ast.ASTKind.ClassDef:
|
||
continue
|
||
vcd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt)
|
||
if vcd is None or vcd.name is None:
|
||
continue
|
||
name_offset: t.CSizeT = idx * RENUM_VARIANT_PER_CLASS + tag
|
||
_renum_variant_names[name_offset] = t.CSizeT(vcd.name)
|
||
_renum_variant_tags[name_offset] = tag
|
||
tag += 1
|
||
|
||
_renum_class_count = idx + 1
|
||
|
||
|
||
# ============================================================
|
||
# _lookup_renum_variant — 查找变体所属的 REnum 类名
|
||
#
|
||
# 参数:
|
||
# variant_name: 变体名(如 "Int"、"Ptr")
|
||
#
|
||
# 返回:
|
||
# 成功: class_name (str)
|
||
# 失败: None
|
||
# 注: tag_value 可通过 _lookup_renum_variant_in_class(class_name, variant_name) 获取
|
||
# ============================================================
|
||
def _lookup_renum_variant(variant_name: str) -> str:
|
||
"""查找变体名所属的 REnum 类名
|
||
|
||
返回: class_name (str),或 None
|
||
"""
|
||
if variant_name is None or _renum_class_names is None:
|
||
return None
|
||
|
||
for i in range(_renum_class_count):
|
||
vcount: int = _renum_class_variant_counts[i]
|
||
for j in range(vcount):
|
||
name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j
|
||
vname: str = _renum_variant_names[name_offset]
|
||
if vname is not None and string.strcmp(vname, variant_name) == 0:
|
||
cls_nm: str = _renum_class_names[i]
|
||
return cls_nm
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# _is_renum_class_name — 检查名称是否是已注册的 REnum 类名
|
||
#
|
||
# 用于 translate_call 检测 ClassName.Variant(args) 形式调用时,
|
||
# 先验证 ClassName 是否是 REnum 类。
|
||
# ============================================================
|
||
def _is_renum_class_name(class_name: str) -> int:
|
||
"""检查名称是否是已注册的 REnum 类名,返回 1=是 / 0=否"""
|
||
if class_name is None or _renum_class_names is None:
|
||
return 0
|
||
for i in range(_renum_class_count):
|
||
existing: str = _renum_class_names[i]
|
||
if existing is not None and string.strcmp(existing, class_name) == 0:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _lookup_renum_variant_in_class — 在指定 REnum 类中查找变体
|
||
#
|
||
# 参数:
|
||
# class_name: REnum 类名
|
||
# variant_name: 变体名
|
||
#
|
||
# 返回:
|
||
# 成功: tag_value (int)
|
||
# 失败: -1
|
||
# ============================================================
|
||
def _lookup_renum_variant_in_class(class_name: str, variant_name: str) -> int:
|
||
"""在指定 REnum 类中查找变体,返回 tag 值或 -1"""
|
||
if class_name is None or variant_name is None or _renum_class_names is None:
|
||
return -1
|
||
for i in range(_renum_class_count):
|
||
existing: str = _renum_class_names[i]
|
||
if existing is None or string.strcmp(existing, class_name) != 0:
|
||
continue
|
||
vcount: int = _renum_class_variant_counts[i]
|
||
for j in range(vcount):
|
||
name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j
|
||
vname: str = _renum_variant_names[name_offset]
|
||
if vname is not None and string.strcmp(vname, variant_name) == 0:
|
||
return _renum_variant_tags[name_offset]
|
||
return -1
|
||
return -1
|
||
|
||
|
||
# ============================================================
|
||
# _register_renum_field_alias — 注册 REnum 变体字段名别名
|
||
#
|
||
# 将变体字段名(如 "Pointee")映射到 payload 索引(如 1),
|
||
# 供 translate_attribute 查找 REnum 变体字段。
|
||
#
|
||
# 参数:
|
||
# pool: 内存分配器
|
||
# class_name: REnum 类名(如 "LLVMType")
|
||
# field_name: 变体字段名(如 "Pointee")
|
||
# payload_idx: payload 索引(1=_p1, 2=_p2, ...)
|
||
# ============================================================
|
||
def _register_renum_field_alias(pool: memhub.MemBuddy | t.CPtr,
|
||
class_name: str,
|
||
field_name: str,
|
||
payload_idx: int):
|
||
"""注册 REnum 变体字段名别名到全局表"""
|
||
global _renum_alias_class, _renum_alias_field, _renum_alias_index
|
||
global _renum_alias_count
|
||
|
||
if pool is None or class_name is None or field_name is None:
|
||
return
|
||
if payload_idx < 1:
|
||
return
|
||
|
||
# 懒初始化表
|
||
if _renum_alias_class is None:
|
||
_renum_alias_class = pool.alloc(8 * RENUM_ALIAS_MAX)
|
||
_renum_alias_field = pool.alloc(8 * RENUM_ALIAS_MAX)
|
||
_renum_alias_index = pool.alloc(8 * RENUM_ALIAS_MAX)
|
||
if (_renum_alias_class is None or _renum_alias_field is None
|
||
or _renum_alias_index is None):
|
||
_renum_alias_class = None
|
||
return
|
||
string.memset(_renum_alias_class, 0, 8 * RENUM_ALIAS_MAX)
|
||
string.memset(_renum_alias_field, 0, 8 * RENUM_ALIAS_MAX)
|
||
string.memset(_renum_alias_index, 0, 8 * RENUM_ALIAS_MAX)
|
||
_renum_alias_count = 0
|
||
|
||
if _renum_alias_count >= RENUM_ALIAS_MAX:
|
||
return
|
||
|
||
# 检查是否已注册(避免重复)— 用 CSizeT 指针值比较,避免 CSizeT→str 转换问题
|
||
cls_key: t.CSizeT = t.CSizeT(class_name)
|
||
fld_key: t.CSizeT = t.CSizeT(field_name)
|
||
for i in range(_renum_alias_count):
|
||
cls_existing: t.CSizeT = _renum_alias_class[i]
|
||
fld_existing: t.CSizeT = _renum_alias_field[i]
|
||
if cls_existing == cls_key and fld_existing == fld_key:
|
||
return
|
||
|
||
idx: int = _renum_alias_count
|
||
_renum_alias_class[idx] = cls_key
|
||
_renum_alias_field[idx] = fld_key
|
||
_renum_alias_index[idx] = t.CSizeT(payload_idx)
|
||
_renum_alias_count = idx + 1
|
||
|
||
|
||
# ============================================================
|
||
# _update_renum_alias_class_ptr — 更新别名表中的 class_name 指针
|
||
#
|
||
# register_struct 会通过 pool.alloc+strcpy 复制类名,导致 entry.Name
|
||
# 与原始 cd.name 是不同指针。别名注册时用 cd.name,查找时用 entry.Name,
|
||
# CSizeT 指针值比较会失败。此函数将别名表中所有匹配 old_ptr 的 class_name
|
||
# 更新为 new_ptr,确保注册和查找使用同一指针。
|
||
#
|
||
# 参数:
|
||
# old_ptr: 旧 class_name 指针值(CSizeT(cd.name))
|
||
# new_ptr: 新 class_name 指针值(CSizeT(entry.Name))
|
||
# ============================================================
|
||
def _update_renum_alias_class_ptr(old_ptr: t.CSizeT, new_ptr: t.CSizeT):
|
||
"""更新别名表中的 class_name 指针,从 old_ptr 更新为 new_ptr"""
|
||
global _renum_alias_class, _renum_alias_count
|
||
|
||
if old_ptr == new_ptr:
|
||
return
|
||
if _renum_alias_class is None:
|
||
return
|
||
for i in range(_renum_alias_count):
|
||
if _renum_alias_class[i] == old_ptr:
|
||
_renum_alias_class[i] = new_ptr
|
||
|
||
|
||
# ============================================================
|
||
# _lookup_renum_field_alias — 查找 REnum 变体字段名的 payload 索引
|
||
#
|
||
# 参数:
|
||
# class_name: REnum 类名(如 "LLVMType")
|
||
# field_name: 变体字段名(如 "Pointee")
|
||
#
|
||
# 返回:
|
||
# 成功: payload 索引(1, 2, ...)
|
||
# 失败: -1
|
||
# ============================================================
|
||
def _lookup_renum_field_alias(class_name: str, field_name: str) -> int:
|
||
"""查找 REnum 变体字段名的 payload 索引,返回索引或 -1
|
||
|
||
class_name: 用 CSizeT 指针值比较(_update_renum_alias_class_ptr 已统一指针)
|
||
field_name: 用 strcmp 内容比较(注册时 vnm.id 与查找时 at.attr 是不同指针)
|
||
"""
|
||
if class_name is None or field_name is None or _renum_alias_class is None:
|
||
return -1
|
||
cls_key: t.CSizeT = t.CSizeT(class_name)
|
||
for i in range(_renum_alias_count):
|
||
cls_existing: t.CSizeT = _renum_alias_class[i]
|
||
if cls_existing == cls_key:
|
||
# field_name 用 strcmp 内容比较(指针不同但内容相同)
|
||
fld_existing_ptr: str = (str | t.CPtr)(
|
||
t.CVoid(_renum_alias_field[i], t.CPtr))
|
||
if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0:
|
||
return _renum_alias_index[i]
|
||
return -1
|
||
|
||
|
||
# ============================================================
|
||
# translate_class_def — 翻译 class 定义
|
||
#
|
||
# 遍历 class body 中的 AnnAssign 语句,收集字段类型
|
||
# 创建 LLVM StructType 并注册到 HandlesStruct
|
||
# ============================================================
|
||
# ============================================================
|
||
# 泛型类模板存储(模块级)
|
||
#
|
||
# 泛型类 class list[T]: 不直接发射 IR,而是存储为模板,
|
||
# 等遇到 list[int](pool) 实例化时触发 _specialize_generic_class
|
||
# ============================================================
|
||
|
||
_generic_class_names: list[str] | t.CPtr = None
|
||
_generic_class_nodes: list[ast.ClassDef | t.CPtr] | t.CPtr = None
|
||
# 追踪每个泛型模板定义模块的 SHA1,用于特化时统一命名空间
|
||
_generic_class_sha1s: list[str] | t.CPtr = None
|
||
|
||
|
||
def _is_generic_class(cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查 ClassDef 是否有类型参数(泛型类),返回 1=是 / 0=否"""
|
||
if cd is None:
|
||
return 0
|
||
tp: list[str] | t.CPtr = cd.type_params
|
||
if tp is None:
|
||
return 0
|
||
if tp.__len__() == 0:
|
||
return 0
|
||
return 1
|
||
|
||
|
||
def _register_generic_template(pool: memhub.MemBuddy | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
module_sha1: str):
|
||
"""注册泛型类模板(类名 + ClassDef 节点 + 来源模块 SHA1)"""
|
||
global _generic_class_names, _generic_class_nodes, _generic_class_sha1s
|
||
if _generic_class_names is None:
|
||
_generic_class_names = list[str](pool, 8)
|
||
_generic_class_nodes = list[ast.ClassDef | t.CPtr](pool, 8)
|
||
_generic_class_sha1s = list[str](pool, 8)
|
||
# 检查是否已注册
|
||
cn: t.CSizeT = _generic_class_names.__len__()
|
||
i: t.CSizeT
|
||
for i in range(cn):
|
||
nm: str = _generic_class_names.get(i)
|
||
if nm is not None and string.strcmp(nm, cd.name) == 0:
|
||
return
|
||
_generic_class_names.append(cd.name)
|
||
_generic_class_nodes.append(cd)
|
||
_generic_class_sha1s.append(module_sha1)
|
||
|
||
|
||
def _find_generic_template(class_name: str) -> ast.ClassDef | t.CPtr:
|
||
"""查找泛型类模板,返回 ClassDef 节点或 None"""
|
||
if _generic_class_names is None or class_name is None:
|
||
return None
|
||
cn: t.CSizeT = _generic_class_names.__len__()
|
||
i: t.CSizeT
|
||
for i in range(cn):
|
||
nm: str = _generic_class_names.get(i)
|
||
if nm is not None and string.strcmp(nm, class_name) == 0:
|
||
# 用局部变量接收 list.get() 结果,触发旧编译器 inttoptr 类型转换
|
||
node: ast.ClassDef | t.CPtr = _generic_class_nodes.get(i)
|
||
return node
|
||
return None
|
||
|
||
|
||
def _find_generic_template_sha1(class_name: str) -> str:
|
||
"""查找泛型类模板的来源模块 SHA1,未找到返回 None"""
|
||
if _generic_class_names is None or class_name is None:
|
||
return None
|
||
cn: t.CSizeT = _generic_class_names.__len__()
|
||
i: t.CSizeT
|
||
for i in range(cn):
|
||
nm: str = _generic_class_names.get(i)
|
||
if nm is not None and string.strcmp(nm, class_name) == 0:
|
||
# 用局部变量接收 list.get() 结果,触发旧编译器 inttoptr 类型转换
|
||
sha1_val: str = _generic_class_sha1s.get(i)
|
||
return sha1_val
|
||
return None
|
||
|
||
|
||
def _mangle_generic_class_name(pool: memhub.MemBuddy | t.CPtr,
|
||
class_name: str,
|
||
type_args: list[str] | t.CPtr) -> str:
|
||
"""生成特化类名: list + [int] -> list[int]
|
||
|
||
分配新缓冲区拼接,避免原地 strcat 导致缓冲区溢出
|
||
"""
|
||
if class_name is None or type_args is None or pool is None:
|
||
return class_name
|
||
n: t.CSizeT = type_args.__len__()
|
||
if n == 0:
|
||
return class_name
|
||
# 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL
|
||
total_len: t.CSizeT = string.strlen(class_name) + 2 # "[" 和 "]"
|
||
i: t.CSizeT
|
||
for i in range(n):
|
||
if i > 0:
|
||
total_len += 1 # ","
|
||
ta: str = type_args.get(i)
|
||
if ta is not None:
|
||
total_len += string.strlen(ta)
|
||
total_len += 1 # NUL
|
||
# 分配新缓冲区
|
||
mangled: str = pool.alloc(total_len)
|
||
if mangled is None:
|
||
return class_name
|
||
mangled[0] = '\0'
|
||
string.strcat(mangled, class_name)
|
||
string.strcat(mangled, "[")
|
||
for i in range(n):
|
||
if i > 0:
|
||
string.strcat(mangled, ",")
|
||
ta: str = type_args.get(i)
|
||
if ta is not None:
|
||
string.strcat(mangled, ta)
|
||
string.strcat(mangled, "]")
|
||
return mangled
|
||
|
||
|
||
# ============================================================
|
||
# 类型注解拷贝(用于泛型特化)
|
||
#
|
||
# _clone_annotation: 拷贝类型注解表达式,替换类型参数 T 为具体类型
|
||
# _clone_arguments: 拷贝 Arguments 节点,替换 arg annotation 中的 T
|
||
# _clone_classdef_for_spec: 拷贝 ClassDef 用于泛型特化
|
||
# ============================================================
|
||
|
||
def _clone_annotation(pool: memhub.MemBuddy | t.CPtr,
|
||
node: ast.AST | t.CPtr,
|
||
tp_names: list[str] | t.CPtr,
|
||
type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr:
|
||
"""拷贝类型注解表达式,替换类型参数 T 为具体类型名
|
||
|
||
tp_names: 类型参数名列表 ['T']
|
||
type_args: 类型实参名列表 ['int']
|
||
"""
|
||
if node is None:
|
||
return None
|
||
k: int = node.kind()
|
||
|
||
# Name: 可能是类型参数 T
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||
if nm.id is not None:
|
||
n: t.CSizeT = tp_names.__len__() if tp_names is not None else 0
|
||
i: t.CSizeT
|
||
for i in range(n):
|
||
tpn: str = tp_names.get(i)
|
||
if tpn is not None and string.strcmp(nm.id, tpn) == 0:
|
||
ta: str = type_args.get(i)
|
||
# 类型实参可能是复合类型(如 "AST|t.CPtr"),用 _parse_type_string_ptr 解析
|
||
# 使用 _ptr 包装避免旧编译器对 ast.AST|t.CPtr 返回类型推断为 i32 的 bug
|
||
parsed_node: ast.AST | t.CPtr = HandlesType._parse_type_string_ptr(pool, ta, nm.ctx)
|
||
return parsed_node
|
||
return ast.Name(pool, nm.id, nm.ctx)
|
||
return None
|
||
|
||
# Attribute: t.CPtr 等
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||
new_value: ast.AST | t.CPtr = _clone_annotation(pool, at.value, tp_names, type_args)
|
||
return ast.Attribute(pool, new_value, at.attr, at.ctx)
|
||
|
||
# BinOp: T | t.CPtr 等
|
||
if k == ast.ASTKind.BinOp:
|
||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||
new_left: ast.AST | t.CPtr = _clone_annotation(pool, bop.left, tp_names, type_args)
|
||
new_right: ast.AST | t.CPtr = _clone_annotation(pool, bop.right, tp_names, type_args)
|
||
return ast.BinOp(pool, new_left, bop.op, new_right)
|
||
|
||
# Subscript: list[int] 等
|
||
if k == ast.ASTKind.Subscript:
|
||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
||
new_value2: ast.AST | t.CPtr = _clone_annotation(pool, sub.value, tp_names, type_args)
|
||
new_slice: ast.AST | t.CPtr = _clone_annotation(pool, sub.slice, tp_names, type_args)
|
||
return ast.Subscript(pool, new_value2, new_slice, sub.ctx)
|
||
|
||
# Tuple: (T, int) 等
|
||
if k == ast.ASTKind.Tuple:
|
||
tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node)
|
||
new_elts: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8)
|
||
if tup.elts is not None:
|
||
tup_elts: list[ast.AST | t.CPtr] | t.CPtr = tup.elts
|
||
en: t.CSizeT = tup_elts.__len__()
|
||
ei: t.CSizeT
|
||
for ei in range(en):
|
||
el: ast.AST | t.CPtr = tup_elts.get(ei)
|
||
new_el: ast.AST | t.CPtr = _clone_annotation(pool, el, tp_names, type_args)
|
||
if new_el is not None:
|
||
new_elts.append(new_el)
|
||
return ast.Tuple(pool, new_elts, tup.ctx)
|
||
|
||
# Constant: 默认值等
|
||
if k == ast.ASTKind.Constant:
|
||
cnst: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||
return ast.Constant(pool, cnst.const_kind, cnst.int_val, cnst.float_val,
|
||
cnst.str_val, cnst.lineno, cnst.col_offset)
|
||
|
||
# 其他: 直接引用(不拷贝)
|
||
return node
|
||
|
||
|
||
def _clone_arguments(pool: memhub.MemBuddy | t.CPtr,
|
||
args: ast.AST | t.CPtr,
|
||
tp_names: list[str] | t.CPtr,
|
||
type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr:
|
||
"""拷贝 Arguments 节点,替换 arg annotation 中的 T"""
|
||
if args is None:
|
||
return None
|
||
if args.kind() != ast.ASTKind.Arguments:
|
||
return args
|
||
old_args: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args)
|
||
# 拷贝 args 列表,替换每个 Arg 的 annotation
|
||
new_arg_list: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8)
|
||
if old_args.args is not None:
|
||
old_arg_list: list[ast.AST | t.CPtr] | t.CPtr = old_args.args
|
||
an: t.CSizeT = old_arg_list.__len__()
|
||
ai: t.CSizeT
|
||
for ai in range(an):
|
||
arg_node: ast.AST | t.CPtr = old_arg_list.get(ai)
|
||
if arg_node is None:
|
||
continue
|
||
if arg_node.kind() == ast.ASTKind.Arg:
|
||
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(arg_node)
|
||
new_anno: ast.AST | t.CPtr = _clone_annotation(pool, ag.annotation, tp_names, type_args)
|
||
new_arg: ast.Arg | t.CPtr = ast.Arg(pool, ag.arg, new_anno)
|
||
new_arg_list.append(new_arg)
|
||
else:
|
||
new_arg_list.append(arg_node)
|
||
return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg,
|
||
old_args.defaults, old_args.kw_defaults)
|
||
|
||
|
||
def _clone_classdef_for_spec(pool: memhub.MemBuddy | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
spec_name: str,
|
||
tp_names: list[str] | t.CPtr,
|
||
type_args: list[str] | t.CPtr) -> ast.ClassDef | t.CPtr:
|
||
"""拷贝 ClassDef 节点用于泛型特化
|
||
|
||
- 替换类名为 spec_name
|
||
- 清除 type_params(特化后不是泛型类)
|
||
- 拷贝 children 中的 AnnAssign 和 FunctionDef,替换类型注解中的 T
|
||
- 方法体直接引用原始节点(通过 type_map 上下文处理 T)
|
||
"""
|
||
# 创建新 ClassDef(type_params=None 表示非泛型)
|
||
new_cd: ast.ClassDef | t.CPtr = ast.ClassDef(pool, spec_name, cd.bases, cd.keywords,
|
||
cd.decorator_list, None)
|
||
# 拷贝 children
|
||
if cd.children is not None:
|
||
cd_children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
cn: t.CSizeT = cd_children.__len__()
|
||
ci: t.CSizeT
|
||
for ci in range(cn):
|
||
child: ast.AST | t.CPtr = cd_children.get(ci)
|
||
if child is None:
|
||
continue
|
||
ck: int = child.kind()
|
||
|
||
if ck == ast.ASTKind.AnnAssign:
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
|
||
new_target: ast.AST | t.CPtr = aa.target
|
||
new_anno2: ast.AST | t.CPtr = _clone_annotation(pool, aa.annotation, tp_names, type_args)
|
||
new_value3: ast.AST | t.CPtr = aa.value
|
||
new_aa: ast.AnnAssign | t.CPtr = ast.AnnAssign(pool, new_target, new_anno2, new_value3, aa.simple)
|
||
new_cd.append(new_aa)
|
||
|
||
elif ck == ast.ASTKind.FunctionDef:
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||
new_args2: ast.AST | t.CPtr = _clone_arguments(pool, fd.args, tp_names, type_args)
|
||
new_returns2: ast.AST | t.CPtr = _clone_annotation(pool, fd.returns, tp_names, type_args)
|
||
new_fd: ast.FunctionDef | t.CPtr = ast.FunctionDef(pool, fd.name, new_args2,
|
||
fd.decorator_list, new_returns2, 0)
|
||
# 方法体直接引用原始节点
|
||
if fd.children is not None:
|
||
fd_children: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||
bcn: t.CSizeT = fd_children.__len__()
|
||
bci: t.CSizeT
|
||
for bci in range(bcn):
|
||
body_stmt: ast.AST | t.CPtr = fd_children.get(bci)
|
||
if body_stmt is not None:
|
||
new_fd.append(body_stmt)
|
||
new_cd.append(new_fd)
|
||
|
||
else:
|
||
new_cd.append(child)
|
||
|
||
return new_cd
|
||
|
||
|
||
# ============================================================
|
||
# 泛型特化缓存(模块级)
|
||
# ============================================================
|
||
|
||
_spec_keys: list[str] | t.CPtr = None
|
||
_spec_names: list[str] | t.CPtr = None
|
||
|
||
|
||
def _find_cached_spec(spec_key: str) -> str:
|
||
"""查找已缓存的特化名,未找到返回 None"""
|
||
if _spec_keys is None or spec_key is None:
|
||
return None
|
||
n: t.CSizeT = _spec_keys.__len__()
|
||
i: t.CSizeT
|
||
for i in range(n):
|
||
k: str = _spec_keys.get(i)
|
||
if k is not None and string.strcmp(k, spec_key) == 0:
|
||
# 用局部变量接收 list.get() 结果,触发旧编译器 inttoptr 类型转换
|
||
spec_nm: str = _spec_names.get(i)
|
||
return spec_nm
|
||
return None
|
||
|
||
|
||
def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str):
|
||
"""缓存特化结果"""
|
||
global _spec_keys, _spec_names
|
||
if _spec_keys is None:
|
||
_spec_keys = list[str](pool, 8)
|
||
_spec_names = list[str](pool, 8)
|
||
_spec_keys.append(spec_key)
|
||
_spec_names.append(spec_name)
|
||
|
||
|
||
def _specialize_generic_class(trans: HT.Translator | t.CPtr,
|
||
class_name: str,
|
||
type_args: list[str] | t.CPtr) -> str:
|
||
"""特化泛型类,返回特化类名
|
||
|
||
1. 查找泛型模板
|
||
2. 生成特化名
|
||
3. 检查缓存
|
||
4. 拷贝 ClassDef 节点(替换类型注解中的 T)
|
||
5. 设置 type_map 上下文(用于方法体中的 T 替换)
|
||
6. 调用 translate_class_def 翻译特化类
|
||
7. 返回特化名
|
||
"""
|
||
if trans is None or class_name is None or type_args is None:
|
||
return None
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
|
||
# ============================================================
|
||
# 诊断输出:追踪 GSListNode 特化调用路径
|
||
# ============================================================
|
||
if string.strcmp(class_name, "GSListNode") == 0:
|
||
VLogger.debug("=== _specialize_generic_class ===", "SPEC")
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "class=%s module=%s", class_name, trans.ModuleSha1)
|
||
VLogger.debug(fb, "SPEC")
|
||
if type_args is not None:
|
||
ta_n: t.CSizeT = type_args.__len__()
|
||
ta_i: t.CSizeT
|
||
for ta_i in range(ta_n):
|
||
ta: str = type_args.get(ta_i)
|
||
if ta is not None:
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, " type_arg[%d]=%s", ta_i, ta)
|
||
VLogger.debug(fb, "SPEC")
|
||
|
||
# 1. 查找泛型模板
|
||
template_cd: ast.ClassDef | t.CPtr = _find_generic_template(class_name)
|
||
if template_cd is None:
|
||
if string.strcmp(class_name, "GSListNode") == 0:
|
||
VLogger.debug("template NOT FOUND, return None", "SPEC")
|
||
return None
|
||
|
||
# 2. 生成特化名
|
||
spec_name: str = _mangle_generic_class_name(pool, class_name, type_args)
|
||
if spec_name is None:
|
||
return None
|
||
|
||
# 3. 检查缓存(spec_key 包含所有类型实参,避免多参数泛型缓存冲突)
|
||
# 分配新缓冲区避免原地 strcat 溢出
|
||
sk_n: t.CSizeT = type_args.__len__()
|
||
sk_total: t.CSizeT = string.strlen(class_name) + 2 # "<" 和 ">"
|
||
sk_i: t.CSizeT
|
||
for sk_i in range(sk_n):
|
||
if sk_i > 0:
|
||
sk_total += 1 # ","
|
||
sk_ta: str = type_args.get(sk_i)
|
||
if sk_ta is not None:
|
||
sk_total += string.strlen(sk_ta)
|
||
sk_total += 1 # NUL
|
||
spec_key: str = pool.alloc(sk_total)
|
||
if spec_key is None:
|
||
return None
|
||
spec_key[0] = '\0'
|
||
string.strcat(spec_key, class_name)
|
||
string.strcat(spec_key, "<")
|
||
for sk_i in range(sk_n):
|
||
if sk_i > 0:
|
||
string.strcat(spec_key, ",")
|
||
sk_ta: str = type_args.get(sk_i)
|
||
if sk_ta is not None:
|
||
string.strcat(spec_key, sk_ta)
|
||
string.strcat(spec_key, ">")
|
||
cached: str = _find_cached_spec(spec_key)
|
||
if cached is not None:
|
||
if string.strcmp(class_name, "GSListNode") == 0:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "CACHE HIT, return cached=%s", cached)
|
||
VLogger.debug(fb, "SPEC")
|
||
return cached
|
||
|
||
# 4. 检查是否已注册(Phase B 重复特化)
|
||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||
if existing is not None:
|
||
if string.strcmp(class_name, "GSListNode") == 0:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "EXISTING registered, return spec_name=%s field_count=%d",
|
||
spec_name, existing.FieldCount)
|
||
VLogger.debug(fb, "SPEC")
|
||
_cache_spec(pool, spec_key, spec_name)
|
||
return spec_name
|
||
|
||
# 预注册缓存(防止递归)
|
||
_cache_spec(pool, spec_key, spec_name)
|
||
|
||
# 5. 拷贝 ClassDef 节点
|
||
tp_names: list[str] | t.CPtr = template_cd.type_params
|
||
spec_cd: ast.ClassDef | t.CPtr = _clone_classdef_for_spec(
|
||
pool, template_cd, spec_name, tp_names, type_args)
|
||
if spec_cd is None:
|
||
return None
|
||
|
||
# 6. 设置 type_map 上下文(用于方法体中的 T 替换)
|
||
trans.GenericTypeParamNames = tp_names
|
||
trans.GenericTypeArgs = type_args
|
||
HandlesType.set_generic_context(tp_names, type_args)
|
||
|
||
# 7. 翻译特化类
|
||
# 切换 trans.ModuleSha1 为泛型模板定义模块的 SHA1,
|
||
# 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀,
|
||
# 与调用端 get_struct_sha1(class_name) 查到的 SHA1 一致。
|
||
saved_module_sha1: str = trans.ModuleSha1
|
||
template_sha1: str = _find_generic_template_sha1(class_name)
|
||
if template_sha1 is not None:
|
||
trans.ModuleSha1 = template_sha1
|
||
translate_class_def(trans, spec_cd)
|
||
# 恢复原始 ModuleSha1
|
||
trans.ModuleSha1 = saved_module_sha1
|
||
|
||
# 8. 清除 type_map 上下文
|
||
trans.GenericTypeParamNames = None
|
||
trans.GenericTypeArgs = None
|
||
HandlesType.clear_generic_context()
|
||
|
||
# 诊断输出:检查特化结果
|
||
if string.strcmp(class_name, "GSListNode") == 0:
|
||
result_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||
if result_entry is not None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "DONE spec_name=%s field_count=%d",
|
||
spec_name, result_entry.FieldCount)
|
||
VLogger.debug(fb, "SPEC")
|
||
# 打印每个字段的类型信息
|
||
ri: int
|
||
for ri in range(result_entry.FieldCount):
|
||
rfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
|
||
result_entry, ri)
|
||
if rfe is not None:
|
||
rfn: str = HandlesStruct.get_field_name_ptr(rfe)
|
||
rft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(rfe)
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, " field[%d] name=%s type=%d",
|
||
ri, rfn if rfn is not None else "(null)",
|
||
t.CSizeT(rft) if rft is not None else 0)
|
||
VLogger.debug(fb, "SPEC")
|
||
else:
|
||
VLogger.debug("DONE but result NOT FOUND in struct table!", "SPEC")
|
||
|
||
return spec_name
|
||
|
||
|
||
def translate_class_def(trans: HT.Translator | t.CPtr,
|
||
node: ast.AST | t.CPtr) -> int:
|
||
"""翻译 class 定义,返回 0"""
|
||
if node is None or trans is None:
|
||
return 0
|
||
|
||
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node)
|
||
if cd is None or cd.name is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
class_name: str = cd.name
|
||
|
||
# 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前,
|
||
# 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类)
|
||
HandlesStruct.add_visible_struct(pool, class_name)
|
||
|
||
# 枚举类:交给 HandlesEnum 处理
|
||
if _is_enum_class(cd) == 1:
|
||
return _translate_enum_def(trans, cd)
|
||
|
||
# 联合体类:交给联合体处理
|
||
if _is_union_class(cd) == 1:
|
||
return _translate_union_def(trans, cd)
|
||
|
||
# REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局)
|
||
if _is_renum_class(cd) == 1:
|
||
return _translate_renum_def(trans, cd)
|
||
|
||
# 泛型类:存储为模板,不发射 IR(等实例化时特化)
|
||
if _is_generic_class(cd) == 1:
|
||
_register_generic_template(pool, cd, trans.ModuleSha1)
|
||
return 0
|
||
|
||
# 检查是否已注册(用 SHA1 区分跨模块同名类)
|
||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
if existing is not None:
|
||
# 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法
|
||
if existing.Ty is not None:
|
||
# Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行)
|
||
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
|
||
# Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体
|
||
# Phase B(declare_only=0)时全量翻译方法体
|
||
if trans._declare_only == 1:
|
||
_translate_oop_methods(trans, cd, existing.Ty, class_name, 1)
|
||
else:
|
||
_translate_oop_methods(trans, cd, existing.Ty, class_name)
|
||
# SHA1 已在 register_struct 时设置,无需再补
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])
|
||
# 必须在 _detect_vtable_status 和父类字段继承之前调用,
|
||
# 否则 find_struct_by_module("GSListNode[Value]") 返回 None
|
||
# ============================================================
|
||
_trigger_base_specialization(trans, cd)
|
||
|
||
# ============================================================
|
||
# VTable 检测:判断是否启用虚表
|
||
# ============================================================
|
||
has_vtable: int = _detect_vtable_status(cd, trans)
|
||
parent_name: str = _get_parent_class(cd, trans)
|
||
is_novtable_deco: int = 0
|
||
if cd.decorator_list is not None:
|
||
if _has_decorator(cd.decorator_list, "NoVTable") == 1:
|
||
is_novtable_deco = 1
|
||
|
||
# ============================================================
|
||
# PhaseA 预注册延迟检查:父类未注册时延迟注册当前类
|
||
#
|
||
# 根因:AssignHandle(HandlesBase.Mixin) 有自己的字段 _CurrentClass,
|
||
# 当 Mixin 未注册时(字母序:HandlesAssign.py 在 HandlesBase.py 之前),
|
||
# field_count=1(不是0),field_count==0 静默返回不触发,
|
||
# AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans)。
|
||
# 后续遍 existing is not None,不补字段 → attribute ptr is None: self.Trans
|
||
#
|
||
# 修复:declare_only==1 且父类未注册时,延迟注册到下一遍。
|
||
# 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。
|
||
# Phase B(declare_only==0)不延迟,避免死锁。
|
||
# ============================================================
|
||
if trans._declare_only == 1 and parent_name is not None:
|
||
parent_check: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if parent_check is None:
|
||
parent_check = HandlesStruct.find_struct(parent_name)
|
||
if parent_check is None:
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 1. 遍历 class body,收集字段信息
|
||
# ============================================================
|
||
# 用 CSizeT 数组存储指针值(64 位系统上 8 字节)
|
||
field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48)
|
||
field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48)
|
||
field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48)
|
||
field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48)
|
||
if field_names_buf is None or field_types_buf is None or field_defaults_buf is None:
|
||
return 0
|
||
if field_annot_buf is None:
|
||
return 0
|
||
string.memset(field_names_buf, 0, 8 * 48)
|
||
string.memset(field_types_buf, 0, 8 * 48)
|
||
string.memset(field_defaults_buf, 0, 8 * 48)
|
||
string.memset(field_annot_buf, 0, 8 * 48)
|
||
|
||
field_count: int = 0
|
||
|
||
# ============================================================
|
||
# 1.5 继承父类字段(字段展平)
|
||
#
|
||
# 父类字段排在子类字段之前,结构体布局:
|
||
# [vtable_ptr?, parent_field1, ..., child_field1, ...]
|
||
# 跳过父类的 __vtable__ 字段(子类会有自己的 vtable 指针)
|
||
# ============================================================
|
||
if parent_name is not None:
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if parent_entry is None:
|
||
# 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin),
|
||
# find_struct_by_module 不回退全局查找,此处手动回退到 find_struct,
|
||
# 否则子类无法继承父类字段 → field_count==0 → __sizeof__ 失败
|
||
parent_entry = HandlesStruct.find_struct(parent_name)
|
||
if parent_entry is not None:
|
||
pfc: int = parent_entry.FieldCount
|
||
for pfi in range(pfc):
|
||
pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
|
||
parent_entry, pfi)
|
||
if pfe is None:
|
||
continue
|
||
pfn: str = HandlesStruct.get_field_name_ptr(pfe)
|
||
if pfn is None:
|
||
continue
|
||
# 跳过父类的 vtable 指针字段
|
||
if string.strcmp(pfn, "__vtable__") == 0:
|
||
continue
|
||
if field_count < 48:
|
||
pft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(pfe)
|
||
pfd: ast.AST | t.CPtr = HandlesStruct.get_field_default_ptr(pfe)
|
||
pfa: str = HandlesStruct.get_field_annot_class_name(pfe)
|
||
field_names_buf[field_count] = t.CSizeT(pfn)
|
||
field_types_buf[field_count] = t.CSizeT(pft)
|
||
if pfd is not None:
|
||
field_defaults_buf[field_count] = t.CSizeT(pfd)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
if pfa is not None:
|
||
stored_val: t.CSizeT = t.CSizeT(pfa)
|
||
field_annot_buf[field_count] = stored_val
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
field_count += 1
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return 0
|
||
|
||
cn: t.CSizeT = children.__len__()
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
sk: int = stmt.kind()
|
||
|
||
if sk != ast.ASTKind.AnnAssign: continue
|
||
|
||
# AnnAssign(target=Name(id), annotation=type, value=...)
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
|
||
if aa is None or aa.target is None:
|
||
continue
|
||
|
||
# 获取字段名
|
||
if aa.target.kind() != ast.ASTKind.Name:
|
||
continue
|
||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||
if tgt.id is None:
|
||
continue
|
||
|
||
# 跳过编译期元数据字段(__provides__/__requires__/__require_must__)
|
||
# 这些字段只用于 with 上下文的静态可达性检查,不生成运行时代码
|
||
# 避免类体中 list 字面量翻译失败(类体无 pool 变量上下文)
|
||
if string.strcmp(tgt.id, "__provides__") == 0:
|
||
continue
|
||
if string.strcmp(tgt.id, "__requires__") == 0:
|
||
continue
|
||
if string.strcmp(tgt.id, "__require_must__") == 0:
|
||
continue
|
||
|
||
# 解析字段类型
|
||
field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||
if field_ty is None:
|
||
field_ty = llvmlite.Int32(pool)
|
||
|
||
# 存储到数组(指针转 CSizeT)
|
||
if field_count < 48:
|
||
diag_name_val: t.CSizeT = t.CSizeT(tgt.id)
|
||
field_names_buf[field_count] = diag_name_val
|
||
field_types_buf[field_count] = t.CSizeT(field_ty)
|
||
# 存储默认值 AST 指针(None=无默认值)
|
||
if aa.value is not None:
|
||
field_defaults_buf[field_count] = t.CSizeT(aa.value)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
# 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体)
|
||
if aa.annotation is not None:
|
||
annot_cn: str = HandlesType.extract_class_name_from_annotation(
|
||
aa.annotation, trans._imported_modules)
|
||
if annot_cn is not None:
|
||
diag_cn_val: t.CSizeT = t.CSizeT(annot_cn)
|
||
field_annot_buf[field_count] = diag_cn_val
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
field_count += 1
|
||
|
||
if field_count == 0:
|
||
# PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描),
|
||
# 导致子类无法继承父类字段 → field_count==0。
|
||
# 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。
|
||
if trans._declare_only == 1 and parent_name is not None:
|
||
return 0
|
||
fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb_cf is not None:
|
||
viperlib.snprintf(fb_cf, 1024, "%s has no fields", class_name)
|
||
VLogger.info(fb_cf, "CLASS")
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 2. 创建 LLVM StructType
|
||
# ============================================================
|
||
# 构建 ParamNode 链表
|
||
first_node: llvmlite.ParamNode | t.CPtr = None
|
||
prev_node: llvmlite.ParamNode | t.CPtr = None
|
||
total_field_count: int = field_count
|
||
|
||
# 如果有虚表,首字段添加 i8* vtable 指针
|
||
if has_vtable == 1:
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if vtable_node is None:
|
||
fb_vn: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb_vn is not None:
|
||
viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name)
|
||
VLogger.error(fb_vn, "CLASS")
|
||
return 0
|
||
string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__())
|
||
vtable_node.Ty = i8_ptr_ty
|
||
first_node = vtable_node
|
||
prev_node = vtable_node
|
||
total_field_count = field_count + 1
|
||
|
||
for fi in range(field_count):
|
||
fty_addr: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr == 0:
|
||
continue
|
||
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr))
|
||
|
||
# 创建 ParamNode
|
||
pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if pnode is None:
|
||
continue
|
||
string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
|
||
pnode.Ty = fty
|
||
|
||
if first_node is None:
|
||
first_node = pnode
|
||
if prev_node is not None:
|
||
prev_node.Next = pnode
|
||
prev_node = pnode
|
||
|
||
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
|
||
type_name: str = class_name
|
||
if trans.ModuleSha1 is not None:
|
||
name_buf: t.CChar | t.CPtr = pool.alloc(64)
|
||
if name_buf is not None:
|
||
viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
|
||
type_name = name_buf
|
||
|
||
# 创建 StructType(命名结构体)
|
||
struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name)
|
||
if struct_ty is None:
|
||
fb_st: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb_st is not None:
|
||
viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name)
|
||
VLogger.error(fb_st, "CLASS")
|
||
return 0
|
||
|
||
# 注册命名结构体到模块(输出 %"name" = type { ... } 定义行)
|
||
llvmlite.module_add_named_type(trans.Module, pool, struct_ty)
|
||
|
||
# 扫描字段类型,为跨模块结构体引用添加 opaque 声明
|
||
# 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque
|
||
for fi in range(field_count):
|
||
fty_addr_op: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr_op == 0:
|
||
continue
|
||
fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr))
|
||
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
|
||
|
||
# ============================================================
|
||
# 3. 注册到 HandlesStruct
|
||
# ============================================================
|
||
entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct(
|
||
pool, class_name, struct_ty, trans.ModuleSha1)
|
||
if entry is None:
|
||
fb_re: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb_re is not None:
|
||
viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name)
|
||
VLogger.error(fb_re, "CLASS")
|
||
return 0
|
||
|
||
# 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错)
|
||
if has_vtable == 1:
|
||
entry.HasVTable = 1
|
||
if is_novtable_deco == 1:
|
||
entry.IsNoVTable = 1
|
||
if parent_name is not None:
|
||
entry.ParentName = parent_name
|
||
|
||
# 添加字段信息
|
||
# 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始
|
||
if has_vtable == 1:
|
||
i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
HandlesStruct.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None)
|
||
|
||
for fi in range(field_count):
|
||
fname_addr: t.CSizeT = field_names_buf[fi]
|
||
if fname_addr == 0:
|
||
continue
|
||
fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
|
||
fty_addr2: t.CSizeT = field_types_buf[fi]
|
||
if fty_addr2 == 0:
|
||
continue
|
||
fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr))
|
||
# 恢复默认值 AST 指针
|
||
fdef_addr: t.CSizeT = field_defaults_buf[fi]
|
||
fdef: ast.AST | t.CPtr = None
|
||
if fdef_addr != 0:
|
||
fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr))
|
||
# 恢复注解类名指针
|
||
fannot_addr: t.CSizeT = field_annot_buf[fi]
|
||
fannot: t.CChar | t.CPtr = None
|
||
if fannot_addr != 0:
|
||
fannot = (t.CChar | t.CPtr)(t.CVoid(fannot_addr, t.CPtr))
|
||
if fname is not None and fty2 is not None:
|
||
HandlesStruct.add_field(pool, entry, fname, fty2, fdef, fannot)
|
||
|
||
# Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体
|
||
if trans._declare_only == 1:
|
||
_translate_oop_methods(trans, cd, struct_ty, class_name, 1)
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__
|
||
# ============================================================
|
||
_translate_oop_methods(trans, cd, struct_ty, class_name)
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# VTable 生成
|
||
#
|
||
# 生成 VTable 全局变量:
|
||
# @"SHA1.ClassName.vtable" = internal constant { i8*, i8*, ... } {
|
||
# i8* bitcast (ret (params)* @"SHA1.ClassName.method1" to i8*),
|
||
# ...
|
||
# }
|
||
#
|
||
# VTable 槽位顺序: class body 中 FunctionDef 的出现顺序
|
||
# ============================================================
|
||
|
||
VTBL_METHOD_MAX: t.CDefine = 32
|
||
|
||
|
||
# _vtable_strcat — 将 src 追加到 dst 末尾
|
||
def _vtable_strcat(dst: t.CChar | t.CPtr, dst_size: t.CSizeT,
|
||
src: t.CChar | t.CPtr):
|
||
"""将 src 追加到 dst 末尾"""
|
||
if dst is None or src is None:
|
||
return
|
||
dlen: t.CSizeT = string.strlen(dst)
|
||
slen: t.CSizeT = string.strlen(src)
|
||
remain: t.CSizeT = dst_size - dlen
|
||
if remain <= 0:
|
||
return
|
||
i: t.CSizeT = 0
|
||
while i < slen and i + 1 < remain:
|
||
dst[dlen + i] = src[i]
|
||
i += 1
|
||
dst[dlen + i] = '\0'
|
||
|
||
|
||
# _vtable_name_needs_quote — 检查 LLVM 标识符是否需要引号
|
||
def _vtable_name_needs_quote(name: str) -> int:
|
||
"""检查 LLVM 标识符是否需要引号(以数字开头或含 '.')"""
|
||
if name is None:
|
||
return 0
|
||
if '0' <= name[0] <= '9':
|
||
return 1
|
||
for i in name:
|
||
if i == '.':
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# _format_func_type_str — 从 Function 对象生成函数类型字符串
|
||
#
|
||
# 格式: ret_ty (param1_ty, param2_ty, ...)
|
||
# 例如: void ({i32, i32}*, i32)
|
||
def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr,
|
||
buf: t.CChar | t.CPtr, buf_size: t.CSizeT,
|
||
func: llvmlite.Function | t.CPtr) -> int:
|
||
"""从 Function 对象生成函数类型字符串"""
|
||
if buf is None or func is None or buf_size == 0:
|
||
return 0
|
||
buf[0] = '\0'
|
||
|
||
# 打印返回类型(使用访问器函数避免跨模块直接字段访问)
|
||
ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func)
|
||
ret_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if ret_buf is not None and ret_ty is not None:
|
||
ret_buf[0] = '\0'
|
||
llvmlite.TypePrint(ret_buf, 128, ret_ty, pool)
|
||
_vtable_strcat(buf, buf_size, ret_buf)
|
||
_vtable_strcat(buf, buf_size, " (")
|
||
|
||
# 遍历参数(使用访问器函数避免跨模块直接字段访问)
|
||
cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
|
||
first: int = 1
|
||
param_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
while cur is not None:
|
||
if first == 0:
|
||
_vtable_strcat(buf, buf_size, ", ")
|
||
if param_buf is not None:
|
||
param_buf[0] = '\0'
|
||
param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur)
|
||
if param_ty is not None:
|
||
llvmlite.TypePrint(param_buf, 128, param_ty, pool)
|
||
_vtable_strcat(buf, buf_size, param_buf)
|
||
cur = llvmlite.param_get_next(cur)
|
||
first = 0
|
||
_vtable_strcat(buf, buf_size, ")")
|
||
return 1
|
||
|
||
|
||
# _generate_vtable — 生成 VTable 全局变量
|
||
#
|
||
# 1. 收集 class body 中所有 FunctionDef 作为虚方法
|
||
# 2. 构造 VTable 类型 { i8*, i8*, ... }
|
||
# 3. 构造初始化字符串 { i8* bitcast (...), ... }
|
||
# 4. 创建全局变量 @"SHA1.ClassName.vtable"
|
||
# 5. 存储虚方法名列表到 StructEntry
|
||
def _generate_vtable(trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""生成 VTable 全局变量"""
|
||
if trans is None or cd is None or class_name is None:
|
||
return 0
|
||
|
||
# 懒导入
|
||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return 0
|
||
cn: t.CSizeT = children.__len__()
|
||
|
||
# 1. 收集虚方法信息
|
||
full_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
|
||
method_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
|
||
# 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法)
|
||
method_parent_sha1s: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
|
||
if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None:
|
||
return 0
|
||
string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX)
|
||
string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX)
|
||
string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX)
|
||
|
||
method_count: int = 0
|
||
|
||
# ============================================================
|
||
# 1.5 继承父类虚方法
|
||
#
|
||
# 父类虚方法排在子类虚方法之前,保持 vtable 槽位顺序一致。
|
||
# 如果子类覆盖了方法,full_name 用子类的;否则用父类的。
|
||
# 用 SHA1 感知查找,规避跨模块同名 find_struct 找错
|
||
# ============================================================
|
||
vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
parent_name: str = None
|
||
if vt_self_entry is not None:
|
||
parent_name = vt_self_entry.ParentName
|
||
if parent_name is not None:
|
||
# 查找父类 entry(优先同模块 SHA1 匹配)
|
||
vt_parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if vt_parent_entry is None:
|
||
# 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找
|
||
vt_parent_entry = HandlesStruct.find_struct(parent_name)
|
||
parent_vt_count: int = 0
|
||
if vt_parent_entry is not None:
|
||
parent_vt_count = vt_parent_entry.VTableMethodCount
|
||
if parent_vt_count > 0:
|
||
for pvi in range(parent_vt_count):
|
||
if method_count >= VTBL_METHOD_MAX:
|
||
break
|
||
pmethod_name: str = None
|
||
if vt_parent_entry is not None:
|
||
pmethod_name = HandlesStruct.get_vtable_method_name(parent_name, pvi)
|
||
if pmethod_name is None:
|
||
continue
|
||
# 检查子类是否覆盖了该方法,以及是否标记 @t.NoVTable
|
||
child_overrides: int = 0
|
||
child_nvt: int = 0
|
||
for ci2 in range(cn):
|
||
stmt2: ast.AST | t.CPtr = children.get(ci2)
|
||
if stmt2 is None:
|
||
continue
|
||
if stmt2.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd2: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt2)
|
||
if fd2 is not None and fd2.name is not None:
|
||
if string.strcmp(fd2.name, pmethod_name) == 0:
|
||
child_overrides = 1
|
||
# 检查子类覆盖方法是否标记 @t.NoVTable
|
||
if fd2.decorator_list is not None:
|
||
if _has_decorator(fd2.decorator_list, "NoVTable") == 1:
|
||
child_nvt = 1
|
||
break
|
||
# 构造 full_name
|
||
# 子类覆盖且未标记 NoVTable → 用子类实现
|
||
# 子类未覆盖 或 子类覆盖但标记 NoVTable → 用父类实现(保持 vtable 槽位)
|
||
pfname_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if pfname_buf is not None:
|
||
if child_overrides == 1 and child_nvt == 0:
|
||
viperlib.snprintf(pfname_buf, 128, "%s.%s", class_name, pmethod_name)
|
||
else:
|
||
viperlib.snprintf(pfname_buf, 128, "%s.%s", parent_name, pmethod_name)
|
||
full_names_buf[method_count] = t.CSizeT(pfname_buf)
|
||
# 复制方法名(短名)
|
||
pmname_len: t.CSizeT = string.strlen(pmethod_name)
|
||
pmname_buf: t.CChar | t.CPtr = pool.alloc(pmname_len + 1)
|
||
if pmname_buf is not None:
|
||
string.strcpy(pmname_buf, pmethod_name)
|
||
method_names_buf[method_count] = t.CSizeT(pmname_buf)
|
||
# 记录 mangling 用的 SHA1(继承未覆盖的方法用父模块 SHA1)
|
||
if child_overrides == 1 and child_nvt == 0:
|
||
# 子类覆盖: 用当前模块 SHA1(保持 0)
|
||
method_parent_sha1s[method_count] = 0
|
||
else:
|
||
# 继承未覆盖: 用父类模块 SHA1
|
||
if vt_parent_entry is not None and vt_parent_entry.ModuleSha1 is not None:
|
||
method_parent_sha1s[method_count] = t.CSizeT(vt_parent_entry.ModuleSha1)
|
||
method_count += 1
|
||
|
||
# 2. 收集当前类的虚方法(跳过已从父类继承的)
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd is None or fd.name is None:
|
||
continue
|
||
if method_count >= VTBL_METHOD_MAX:
|
||
break
|
||
|
||
mname: str = fd.name
|
||
# 跳过构造函数和特殊方法(不应放入虚表)
|
||
if string.strcmp(mname, "__init__") == 0:
|
||
continue
|
||
if string.strcmp(mname, "__before_init__") == 0:
|
||
continue
|
||
if string.strcmp(mname, "__new__") == 0:
|
||
continue
|
||
# 函数级装饰器过滤:判断方法是否应该进入虚表
|
||
if _should_method_be_virtual(cd, fd, trans) == 0:
|
||
continue
|
||
# 检查是否已从父类继承(避免重复)
|
||
already_in_vt: int = 0
|
||
for mi in range(method_count):
|
||
exist_addr: t.CSizeT = method_names_buf[mi]
|
||
if exist_addr != 0:
|
||
exist_name: str = (str | t.CPtr)(t.CVoid(exist_addr, t.CPtr))
|
||
if exist_name is not None and string.strcmp(exist_name, mname) == 0:
|
||
already_in_vt = 1
|
||
break
|
||
if already_in_vt == 1:
|
||
continue
|
||
# 构造 full_name = "ClassName.method_name"
|
||
fname_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if fname_buf is not None:
|
||
viperlib.snprintf(fname_buf, 128, "%s.%s", class_name, mname)
|
||
full_names_buf[method_count] = t.CSizeT(fname_buf)
|
||
|
||
# 复制方法名
|
||
mname_len: t.CSizeT = string.strlen(mname)
|
||
mname_buf: t.CChar | t.CPtr = pool.alloc(mname_len + 1)
|
||
if mname_buf is not None:
|
||
string.strcpy(mname_buf, mname)
|
||
method_names_buf[method_count] = t.CSizeT(mname_buf)
|
||
|
||
method_count += 1
|
||
|
||
if method_count == 0:
|
||
return 0
|
||
|
||
# 2. 构造 VTable 类型: { i8*, i8*, ..., i8* }
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
first_node: llvmlite.ParamNode | t.CPtr = None
|
||
tail_node: llvmlite.ParamNode | t.CPtr = None
|
||
for i in range(method_count):
|
||
pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
|
||
if pnode is None:
|
||
continue
|
||
tail_node = llvmlite.param_list_append(first_node, tail_node, pnode)
|
||
if first_node is None:
|
||
first_node = tail_node
|
||
|
||
vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, method_count, None)
|
||
if vtable_ty is None:
|
||
return 0
|
||
|
||
# 3. 构造初始化字符串
|
||
init_buf: t.CChar | t.CPtr = pool.alloc(4096)
|
||
if init_buf is None:
|
||
return 0
|
||
init_buf[0] = '\0'
|
||
_vtable_strcat(init_buf, 4096, "{ ")
|
||
|
||
for i in range(method_count):
|
||
if i > 0:
|
||
_vtable_strcat(init_buf, 4096, ", ")
|
||
|
||
full_name_addr: t.CSizeT = full_names_buf[i]
|
||
if full_name_addr == 0:
|
||
_vtable_strcat(init_buf, 4096, "i8* null")
|
||
continue
|
||
|
||
full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr))
|
||
|
||
# 检查是否是继承方法(method_parent_sha1s 非 0 表示用父模块 SHA1 mangling)
|
||
parent_sha1_addr: t.CSizeT = method_parent_sha1s[i]
|
||
if parent_sha1_addr != 0:
|
||
# 继承方法: 用父类模块 SHA1 做 mangling
|
||
parent_sha1: str = (str | t.CPtr)(t.CVoid(parent_sha1_addr, t.CPtr))
|
||
mangled_name: str = HandlesFunctions._mangle_name_with_sha1(parent_sha1, full_name)
|
||
# 从全局函数表查找(跨模块函数不在当前模块表中)
|
||
func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_global(full_name)
|
||
else:
|
||
# 当前类方法: 用当前模块 SHA1
|
||
mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)
|
||
func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_table(
|
||
trans._funcs, trans._func_count, full_name)
|
||
# 当前模块表找不到时,回退到全局表
|
||
if func is None:
|
||
func = HandlesExprCall.find_func_global(full_name)
|
||
|
||
if func is None:
|
||
_vtable_strcat(init_buf, 4096, "i8* null")
|
||
continue
|
||
|
||
# 构造函数类型字符串
|
||
func_ty_buf: t.CChar | t.CPtr = pool.alloc(512)
|
||
if func_ty_buf is None:
|
||
_vtable_strcat(init_buf, 4096, "i8* null")
|
||
continue
|
||
_format_func_type_str(pool, func_ty_buf, 512, func)
|
||
|
||
# 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
|
||
_vtable_strcat(init_buf, 4096, "i8* bitcast (")
|
||
_vtable_strcat(init_buf, 4096, func_ty_buf)
|
||
_vtable_strcat(init_buf, 4096, "* @")
|
||
|
||
if _vtable_name_needs_quote(mangled_name) != 0:
|
||
_vtable_strcat(init_buf, 4096, "\"")
|
||
_vtable_strcat(init_buf, 4096, mangled_name)
|
||
_vtable_strcat(init_buf, 4096, "\"")
|
||
else:
|
||
_vtable_strcat(init_buf, 4096, mangled_name)
|
||
_vtable_strcat(init_buf, 4096, " to i8*)")
|
||
|
||
_vtable_strcat(init_buf, 4096, " }")
|
||
|
||
# 4. 构造 VTable 全局变量名
|
||
vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if vtable_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name)
|
||
vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf)
|
||
|
||
# 5. 创建全局变量
|
||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
|
||
pool, vtable_mangled, vtable_ty)
|
||
if gv is None:
|
||
return 0
|
||
gv.Initializer = init_buf
|
||
gv.IsConstant = 1
|
||
gv.Linkage = "internal"
|
||
|
||
# 添加到模块
|
||
llvmlite.module_add_global(mod, gv)
|
||
|
||
# 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错)
|
||
if vt_self_entry is not None:
|
||
vt_self_entry.VTableMethods = method_names_buf
|
||
vt_self_entry.VTableMethodCount = method_count
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# OOP 方法翻译
|
||
#
|
||
# 存在任意 FunctionDef 的 class 自动升级为 OOP 结构体。
|
||
# 方法翻译为 SHA1.ClassName.method_name(self: Ptr(StructTy), ...) 函数。
|
||
# self 参数直接注册为 SSA 值(不创建 alloca),使 self.field 能通过 GEP 直接访问。
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# _translate_oop_methods — 扫描 class body 中的方法并翻译
|
||
#
|
||
# 遍历 ClassDef.children,对每个 FunctionDef:
|
||
# - 标记 OOP(mark_as_oop)
|
||
# - 如果是 __init__,标记 has_init
|
||
# - 翻译方法(生成 SHA1.ClassName.method_name 函数)
|
||
# 翻译完所有方法后,生成 __before_init__ 函数
|
||
# ============================================================
|
||
def _translate_oop_methods(trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str,
|
||
mark_only: int = 0) -> int:
|
||
"""扫描 class body 中的方法并翻译,生成 __before_init__
|
||
|
||
mark_only: 0=全量翻译(默认),1=只设置 IsOOP/HasNew/HasInit 标志(不翻译方法体)
|
||
"""
|
||
if trans is None or cd is None or struct_ty is None or class_name is None:
|
||
return 0
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return 0
|
||
|
||
cn: t.CSizeT = children.__len__()
|
||
has_method: int = 0
|
||
has_init: int = 0
|
||
has_new: int = 0
|
||
|
||
# 提前用类型指针定位 entry(规避跨模块同名类 find_struct 找错)
|
||
oop_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty)
|
||
|
||
# 第一遍:检测是否有方法,标记 OOP
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() == ast.ASTKind.FunctionDef:
|
||
has_method = 1
|
||
fd_check: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd_check is not None and fd_check.name is not None:
|
||
if string.strcmp(fd_check.name, "__init__") == 0:
|
||
has_init = 1
|
||
if string.strcmp(fd_check.name, "__new__") == 0:
|
||
has_new = 1
|
||
|
||
if has_method == 0:
|
||
# 子类没有自己的方法,但可能继承了父类的虚方法
|
||
# 用 oop_entry 直接获取 ParentName,规避 find_struct 按名查找找错
|
||
parent_name: str = None
|
||
if oop_entry is not None:
|
||
parent_name = oop_entry.ParentName
|
||
if parent_name is not None:
|
||
parent_vt_count: int = HandlesStruct.get_vtable_method_count(parent_name)
|
||
if parent_vt_count > 0:
|
||
has_method = 1 # 标记为有方法(继承的虚方法)
|
||
if has_method == 0:
|
||
return 0
|
||
|
||
# 标记为 OOP 结构体
|
||
if oop_entry is not None:
|
||
oop_entry.IsOOP = 1
|
||
if has_init != 0:
|
||
oop_entry.HasInit = 1
|
||
if has_new != 0:
|
||
oop_entry.HasNew = 1
|
||
|
||
# mark_only 模式:只设置标志,不翻译方法体
|
||
if mark_only != 0:
|
||
return 0
|
||
|
||
# 第二遍:翻译每个方法
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() == ast.ASTKind.FunctionDef:
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd is not None and fd.name is not None:
|
||
_translate_method(trans, fd, struct_ty, class_name)
|
||
|
||
# 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount)
|
||
# 必须在 __before_init__ 之前,否则 __before_init__ 读不到 VTableMethodCount
|
||
# 用 oop_entry 直接检查,规避跨模块同名 find_struct 找错
|
||
has_vt_flag: int = 0
|
||
if oop_entry is not None:
|
||
has_vt_flag = oop_entry.HasVTable
|
||
if has_vt_flag == 1:
|
||
_generate_vtable(trans, cd, class_name)
|
||
|
||
# 生成 __before_init__ 函数(零值填充 + 默认值赋值 + vtable 指针设置)
|
||
_generate_before_init(trans, struct_ty, class_name)
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _translate_method — 翻译单个方法
|
||
#
|
||
# 生成: define <ret_ty> @SHA1.ClassName.method_name(Ptr(StructTy) %self, ...)
|
||
#
|
||
# self 参数处理:
|
||
# - 类型 Ptr(struct_ty),直接注册为 SSA 值(不创建 alloca)
|
||
# - 使 self.field 能通过 GEP 直接访问原始结构体
|
||
# ============================================================
|
||
def _translate_method(trans: HT.Translator | t.CPtr,
|
||
fd: ast.FunctionDef | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""翻译单个方法,返回 0"""
|
||
if trans is None or fd is None or struct_ty is None or class_name is None:
|
||
return 0
|
||
|
||
# 懒导入
|
||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesBody as HandlesBody
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
imported_modules: str = trans._imported_modules
|
||
from_imports: str = trans._from_imports
|
||
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
|
||
func_count: int = trans._func_count
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
|
||
|
||
method_name: str = fd.name
|
||
|
||
# 构建方法全名: ClassName.method_name
|
||
full_name_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if full_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name)
|
||
full_name: str = full_name_buf
|
||
|
||
# SHA1 命名空间混淆
|
||
mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)
|
||
|
||
# 推断返回类型
|
||
ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||
if fd.returns is not None:
|
||
ret_ty = HandlesType.resolve_annotation_type(
|
||
pool, fd.returns, imported_modules, from_imports, trans)
|
||
if ret_ty is None and fd.returns is not None:
|
||
if HandlesType.has_decorator_marker(fd.returns, "State") != 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
if ret_ty is None:
|
||
# __init__ 和 __before_init__ 返回 void
|
||
if string.strcmp(method_name, "__init__") == 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
# __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间)
|
||
elif string.strcmp(method_name, "__new__") == 0:
|
||
ret_ty = llvmlite.Ptr(pool, struct_ty)
|
||
else:
|
||
param_types_str: str = HandlesType.build_param_types_str(pool, fd.args)
|
||
ret_ty = HandlesType.infer_return_type(
|
||
pool, fd.children, param_types_str)
|
||
|
||
# 创建 LLVM 函数
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||
pool, mod, mangled_name, ret_ty)
|
||
if func is None:
|
||
return 0
|
||
|
||
# 提取默认参数信息(方法的 args[0] 是 self,不含在 param_count 中)
|
||
md_defaults: list[ast.AST | t.CPtr] | t.CPtr = None
|
||
md_default_count: int = 0
|
||
md_param_count: int = 0
|
||
md_args_node: ast.Arguments | t.CPtr = fd.args
|
||
if md_args_node is not None:
|
||
md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node)
|
||
if md_ags.args is not None:
|
||
md_param_count = md_ags.args.__len__() - 1
|
||
if md_ags.defaults is not None:
|
||
md_defaults = md_ags.defaults
|
||
md_default_count = md_ags.defaults.__len__()
|
||
|
||
# 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配)
|
||
max_funcs: int = 256
|
||
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs,
|
||
md_defaults, md_default_count, md_param_count) == 0:
|
||
trans._func_count = func_count + 1
|
||
|
||
# 添加 self 参数(Ptr(struct_ty))
|
||
llvmlite.add_param(pool, func, self_ptr_ty, "%self")
|
||
|
||
# 添加其他参数(支持类型注解,跳过索引 0 的 self 参数)
|
||
args_node: ast.Arguments | t.CPtr = fd.args
|
||
if args_node is not None:
|
||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||
an: t.CSizeT = alist.__len__()
|
||
for ai in range(1, an):
|
||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||
if arg is not None and arg.arg is not None:
|
||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg.annotation, imported_modules, from_imports, trans)
|
||
if resolved is not None:
|
||
param_ty = resolved
|
||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname is not None:
|
||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||
llvmlite.add_param(pool, func, param_ty, pname)
|
||
|
||
# 创建 entry 块
|
||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||
if entry_blk is None:
|
||
return 0
|
||
|
||
# 创建方法专属 builder
|
||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# 进入函数作用域
|
||
HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION)
|
||
|
||
# 注册 self 为 SSA 值(不创建 alloca,不 store)
|
||
# 这样 self.field 通过 lookup_var 获取 Ptr(struct_ty) 后直接 GEP
|
||
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
|
||
HandlesVar.define_var(trans.SymTab, "self", self_val)
|
||
# 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用)
|
||
HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)
|
||
|
||
# 为其他参数创建 alloca 并 store(与普通函数一致,跳过索引 0 的 self 参数)
|
||
if args_node is not None:
|
||
ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags2.args is not None:
|
||
alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args
|
||
an2: t.CSizeT = alist2.__len__()
|
||
for ai2 in range(1, an2):
|
||
arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2))
|
||
if arg2 is not None and arg2.arg is not None:
|
||
param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg2.annotation is not None:
|
||
resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg2.annotation, imported_modules, from_imports, trans)
|
||
if resolved2 is not None:
|
||
param_ty2 = resolved2
|
||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2)
|
||
if alloca is not None:
|
||
HandlesVar.define_var(trans.SymTab, arg2.arg, alloca)
|
||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||
if arg2.annotation is not None:
|
||
cls_nm_oc: str = HandlesType.extract_class_name_from_annotation(
|
||
arg2.annotation, imported_modules)
|
||
if cls_nm_oc is not None:
|
||
HandlesVar.set_var_annot_class_name(
|
||
trans.SymTab, arg2.arg, cls_nm_oc)
|
||
pname2: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname2 is not None:
|
||
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
|
||
param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||
pool, param_ty2, pname2)
|
||
llvmlite.build_store(func_builder, param_val, alloca)
|
||
|
||
# 保存模块级作用域状态
|
||
old_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||
old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||
old_global_count: int = trans._global_name_count
|
||
old_nonlocal_count: int = trans._nonlocal_name_count
|
||
old_env_count: int = trans._closure_env_count
|
||
|
||
trans._cur_func = func
|
||
trans._cur_builder = func_builder
|
||
HT.clear_scope_names(trans)
|
||
|
||
# 预扫描方法体:为局部变量提前创建 alloca
|
||
body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||
if body is not None:
|
||
bn: t.CSizeT = body.__len__()
|
||
for bi in range(bn):
|
||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||
if stmt is not None:
|
||
HandlesBody.pre_scan_allocas(trans, stmt)
|
||
|
||
# 翻译方法体
|
||
if body is not None:
|
||
bn2: t.CSizeT = body.__len__()
|
||
for bi2 in range(bn2):
|
||
stmt2: ast.AST | t.CPtr = body.get(bi2)
|
||
if stmt2 is not None:
|
||
HandlesBody.translate_stmt(trans, stmt2)
|
||
|
||
# 如果返回类型为 void,添加 ret void;否则添加隐式 ret 0
|
||
is_void: int = 0
|
||
if ret_ty is not None:
|
||
match ret_ty:
|
||
case llvmlite.LLVMType.Void():
|
||
is_void = 1
|
||
|
||
if is_void != 0:
|
||
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
|
||
llvmlite.build_ret_void(func_builder)
|
||
else:
|
||
last_is_return: int = 0
|
||
if body is not None:
|
||
bn3: t.CSizeT = body.__len__()
|
||
if bn3 > 0:
|
||
last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
|
||
last_is_return = 1
|
||
if last_is_return == 0:
|
||
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
|
||
# 根据返回类型生成正确的零值返回
|
||
_m_is_void: int = 0
|
||
_m_is_ptr: int = 0
|
||
if ret_ty is not None:
|
||
match ret_ty:
|
||
case llvmlite.LLVMType.Void():
|
||
_m_is_void = 1
|
||
case llvmlite.LLVMType.Ptr(_m_pe):
|
||
_m_is_ptr = 1
|
||
if _m_is_void != 0:
|
||
llvmlite.build_ret_void(func_builder)
|
||
elif _m_is_ptr != 0:
|
||
_m_null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null")
|
||
llvmlite.build_ret(func_builder, _m_null_val)
|
||
else:
|
||
_m_zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||
llvmlite.build_ret(func_builder, _m_zero_val)
|
||
|
||
# 恢复模块级作用域
|
||
HandlesVar.exit_scope(trans.SymTab)
|
||
trans._cur_func = old_func
|
||
trans._cur_builder = old_builder
|
||
trans._global_name_count = old_global_count
|
||
trans._nonlocal_name_count = old_nonlocal_count
|
||
trans._closure_env_count = old_env_count
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _generate_before_init — 生成 __before_init__ 函数
|
||
#
|
||
# 生成: define void @SHA1.ClassName.__before_init__(Ptr(StructTy) %self)
|
||
#
|
||
# 执行:
|
||
# 1. store zeroinitializer 到 %self(零值填充)
|
||
# 2. 逐字段 store 默认值(如有)
|
||
# 3. ret void
|
||
# ============================================================
|
||
def _generate_before_init(trans: HT.Translator | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""生成 __before_init__ 函数,返回 0"""
|
||
if trans is None or struct_ty is None or class_name is None:
|
||
return 0
|
||
|
||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
|
||
func_count: int = trans._func_count
|
||
|
||
self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
|
||
void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||
|
||
# 构建函数名: ClassName.__before_init__
|
||
full_name_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if full_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name)
|
||
full_name: str = full_name_buf
|
||
|
||
mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)
|
||
|
||
# 创建函数
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||
pool, mod, mangled_name, void_ty)
|
||
if func is None:
|
||
return 0
|
||
|
||
# 注册到函数表
|
||
max_funcs: int = 256
|
||
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs) == 0:
|
||
trans._func_count = func_count + 1
|
||
|
||
# 添加 self 参数
|
||
llvmlite.add_param(pool, func, self_ptr_ty, "%self")
|
||
|
||
# 创建 entry 块 + builder
|
||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||
if entry_blk is None:
|
||
return 0
|
||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# 注册 self 为 SSA 值
|
||
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
|
||
|
||
# 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self
|
||
zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty)
|
||
if zero is not None:
|
||
llvmlite.build_store(func_builder, zero, self_val)
|
||
|
||
# 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0)
|
||
# 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错
|
||
bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty)
|
||
bi_has_vt: int = 0
|
||
if bi_entry is not None:
|
||
bi_has_vt = bi_entry.HasVTable
|
||
if bi_has_vt == 1:
|
||
vt_method_count: int = 0
|
||
if bi_entry is not None:
|
||
vt_method_count = bi_entry.VTableMethodCount
|
||
if vt_method_count > 0:
|
||
# 构造 vtable 类型 { i8*, i8*, ..., i8* }
|
||
vt_i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
vt_i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_i8_ty)
|
||
|
||
vt_first_node: llvmlite.ParamNode | t.CPtr = None
|
||
vt_prev_node: llvmlite.ParamNode | t.CPtr = None
|
||
for vti in range(vt_method_count):
|
||
vtnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, vt_i8_ptr_ty)
|
||
if vtnode is None:
|
||
continue
|
||
if vt_first_node is None:
|
||
vt_first_node = vtnode
|
||
if vt_prev_node is not None:
|
||
llvmlite.paramnode_set_next(vt_prev_node, vtnode)
|
||
vt_prev_node = vtnode
|
||
|
||
vt_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first_node, vt_method_count, None)
|
||
vt_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_ty)
|
||
|
||
# 构造 vtable 全局变量名
|
||
vt_name_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||
if vt_name_buf is not None:
|
||
viperlib.snprintf(vt_name_buf, 128, "%s.vtable", class_name)
|
||
vt_full_name: str = vt_name_buf
|
||
vt_mangled: str = HandlesFunctions._mangle_name(trans, vt_full_name)
|
||
|
||
# GEP 到 __vtable__ 字段(索引 0)
|
||
vt_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
|
||
if vt_slot is not None:
|
||
# 创建全局变量引用 Value
|
||
vt_ref: llvmlite.Value | t.CPtr = llvmlite.new_value(pool)
|
||
if vt_ref is not None:
|
||
llvmlite.value_set_ty(vt_ref, vt_ptr_ty)
|
||
llvmlite.value_set_isconst(vt_ref, 1)
|
||
# Name 格式: @"mangled" 或 @mangled
|
||
vt_ref_name: t.CChar | t.CPtr = pool.alloc(256)
|
||
if vt_ref_name is not None:
|
||
vt_ref_name[0] = '\0'
|
||
if _vtable_name_needs_quote(vt_mangled) != 0:
|
||
viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled)
|
||
else:
|
||
viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled)
|
||
llvmlite.value_set_name(vt_ref, vt_ref_name)
|
||
|
||
# bitcast 到 i8*
|
||
vt_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
func_builder, vt_ref, vt_i8_ptr_ty)
|
||
if vt_as_i8 is not None:
|
||
llvmlite.build_store(func_builder, vt_as_i8, vt_slot)
|
||
|
||
# 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错)
|
||
if bi_entry is not None:
|
||
for fi in range(bi_entry.FieldCount):
|
||
fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
|
||
bi_entry, fi)
|
||
if fe is None or fe.DefaultVal is None:
|
||
continue
|
||
# 翻译默认值表达式
|
||
default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
|
||
if default_val is None:
|
||
continue
|
||
# GEP 到字段
|
||
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
func_builder, struct_ty, fe.Ty, self_val, fe.Index)
|
||
if field_ptr is None:
|
||
continue
|
||
# 类型转换并 store
|
||
default_val = HandlesExpr.coerce_to_type(func_builder, default_val, fe.Ty)
|
||
llvmlite.build_store(func_builder, default_val, field_ptr)
|
||
|
||
# 3. ret void
|
||
llvmlite.build_ret_void(func_builder)
|
||
|
||
return 0
|