import t, c from stdint import * import ast import llvmlite import memhub import string import stdio import viperlib 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.HandlesEnum as HandlesEnum # 枚举成员临时数组最大数量(本地常量) ENUM_MEMBER_MAX_LOCAL: t.CDefine = 64 # ============================================================ # 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 # ============================================================ # 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: stdio.printf("[ENUM] %s has no body\n", class_name) 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 if member_count == 0: stdio.printf("[ENUM] %s has no members\n", class_name) 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: stdio.printf("[ENUM] failed to register %s\n", class_name) 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) stdio.printf("[ENUM] registered %s with %d members, base_bits=%d\n", class_name, member_count, max_bits) 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: stdio.printf("[UNION] %s has no body\n", class_name) return 0 cn: t.CSizeT = children.__len__() # 临时数组存储字段信息 field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32) field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32) if field_names_buf is None or field_types_buf is None: return 0 string.memset(field_names_buf, 0, 8 * 32) string.memset(field_types_buf, 0, 8 * 32) 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) 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 < 32: 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: stdio.printf("[UNION] %s has no fields\n", class_name) 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: stdio.printf("[UNION] failed to create type for %s\n", class_name) 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: stdio.printf("[UNION] failed to register %s\n", class_name) 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) stdio.printf("[UNION] registered %s with %d fields, max_size=%d\n", class_name, field_count, max_size) return 0 # ============================================================ # 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 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): """注册泛型类模板(类名 + ClassDef 节点)""" global _generic_class_names, _generic_class_nodes if _generic_class_names is None: _generic_class_names = list[str](pool, 8) _generic_class_nodes = list[ast.ClassDef | t.CPtr](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) 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: return _generic_class_nodes.get(i) 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 解析 return HandlesType._parse_type_string(pool, ta, nm.ctx) 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: 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: an: t.CSizeT = old_args.args.__len__() ai: t.CSizeT for ai in range(an): arg_node: ast.AST | t.CPtr = old_args.args.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: 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: 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: return _spec_names.get(i) 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: stdio.printf("[SPEC] === _specialize_generic_class ===\n") stdio.printf("[SPEC] class=%s module=%s\n", class_name, trans.ModuleSha1) 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: stdio.printf("[SPEC] type_arg[%d]=%s\n", ta_i, ta) stdio.fflush(0) # 1. 查找泛型模板 template_cd: ast.ClassDef | t.CPtr = _find_generic_template(class_name) if template_cd is None: if string.strcmp(class_name, "GSListNode") == 0: stdio.printf("[SPEC] template NOT FOUND, return None\n") stdio.fflush(0) 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: stdio.printf("[SPEC] CACHE HIT, return cached=%s\n", cached) stdio.fflush(0) 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: stdio.printf("[SPEC] EXISTING registered, return spec_name=%s field_count=%d\n", spec_name, existing.FieldCount) stdio.fflush(0) _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. 翻译特化类 translate_class_def(trans, spec_cd) # 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: stdio.printf("[SPEC] DONE spec_name=%s field_count=%d\n", spec_name, result_entry.FieldCount) # 打印每个字段的类型信息 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) stdio.printf("[SPEC] field[%d] name=%s type=%d\n", ri, rfn if rfn is not None else "(null)", t.CSizeT(rft) if rft is not None else 0) else: stdio.printf("[SPEC] DONE but result NOT FOUND in struct table!\n") stdio.fflush(0) 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) # 泛型类:存储为模板,不发射 IR(等实例化时特化) if _is_generic_class(cd) == 1: _register_generic_template(pool, cd) return 0 # 检查是否已注册(用 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: # Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行) llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) _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 # ============================================================ # 1. 遍历 class body,收集字段信息 # ============================================================ # 用 CSizeT 数组存储指针值(64 位系统上 8 字节) field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32) field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32) field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32) field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32) 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 * 32) string.memset(field_types_buf, 0, 8 * 32) string.memset(field_defaults_buf, 0, 8 * 32) string.memset(field_annot_buf, 0, 8 * 32) 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 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 < 32: 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) if field_ty is None: field_ty = llvmlite.Int32(pool) # 存储到数组(指针转 CSizeT) if field_count < 32: 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: stdio.printf("[CLASS] %s has no fields\n", class_name) 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: stdio.printf("[CLASS] failed to alloc vtable node for %s\n", class_name) 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: stdio.printf("[CLASS] failed to create StructType for %s\n", class_name) 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: stdio.printf("[CLASS] failed to register %s\n", class_name) 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) 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 # 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配) 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 参数(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) 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, HandlesVar.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) 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: # __new__ 返回指针类型,隐式返回 null 指针 if string.strcmp(method_name, "__new__") == 0: null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") llvmlite.build_ret(func_builder, null_val) else: zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) llvmlite.build_ret(func_builder, 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