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