Files
TransPyC/TransPyV/App/lib/core/Handles/HandlesClassDef.py
2026-07-26 20:32:26 +08:00

3335 lines
136 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 形式Namefrom 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.Statei32 默认),优先返回具体类型
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.nameAST 原始指针),
# 但查找时用 entry.Nameregister_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 字段(位置 0i32
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
"""
# 创建新 ClassDeftype_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-predeclare_only=1多遍扫描时类已注册但不应翻译方法体
# Phase Bdeclare_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不是0field_count==0 静默返回不触发,
# AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans
# 后续遍 existing is not None不补字段 → attribute ptr is None: self.Trans
#
# 修复declare_only==1 且父类未注册时,延迟注册到下一遍。
# 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。
# Phase Bdeclare_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 mangling0=当前类方法)
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:
# - 标记 OOPmark_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